Bug Summary

File:out/../deps/icu-small/source/common/ucnv.cpp
Warning:line 1937, column 21
Although the value stored to 's' is used in the enclosing expression, the value is never actually read from 's'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ucnv.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D U_COMMON_IMPLEMENTATION=1 -D U_ATTRIBUTE_DEPRECATED= -D _CRT_SECURE_NO_DEPRECATE= -D U_STATIC_IMPLEMENTATION=1 -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/icu-small/source/common -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-deprecated-declarations -Wno-strict-aliasing -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/icu-small/source/common/ucnv.cpp
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4******************************************************************************
5*
6* Copyright (C) 1998-2016, International Business Machines
7* Corporation and others. All Rights Reserved.
8*
9******************************************************************************
10*
11* ucnv.c:
12* Implements APIs for the ICU's codeset conversion library;
13* mostly calls through internal functions;
14* created by Bertrand A. Damiba
15*
16* Modification History:
17*
18* Date Name Description
19* 04/04/99 helena Fixed internal header inclusion.
20* 05/09/00 helena Added implementation to handle fallback mappings.
21* 06/20/2000 helena OS/400 port changes; mostly typecast.
22*/
23
24#include "unicode/utypes.h"
25
26#if !UCONFIG_NO_CONVERSION0
27
28#include <memory>
29
30#include "unicode/ustring.h"
31#include "unicode/ucnv.h"
32#include "unicode/ucnv_err.h"
33#include "unicode/uset.h"
34#include "unicode/utf.h"
35#include "unicode/utf16.h"
36#include "putilimp.h"
37#include "cmemory.h"
38#include "cstring.h"
39#include "uassert.h"
40#include "utracimp.h"
41#include "ustr_imp.h"
42#include "ucnv_imp.h"
43#include "ucnv_cnv.h"
44#include "ucnv_bld.h"
45
46/* size of intermediate and preflighting buffers in ucnv_convert() */
47#define CHUNK_SIZE1024 1024
48
49typedef struct UAmbiguousConverter {
50 const char *name;
51 const UChar variant5c;
52} UAmbiguousConverter;
53
54static const UAmbiguousConverter ambiguousConverters[]={
55 { "ibm-897_P100-1995", 0xa5 },
56 { "ibm-942_P120-1999", 0xa5 },
57 { "ibm-943_P130-1999", 0xa5 },
58 { "ibm-946_P100-1995", 0xa5 },
59 { "ibm-33722_P120-1999", 0xa5 },
60 { "ibm-1041_P100-1995", 0xa5 },
61 /*{ "ibm-54191_P100-2006", 0xa5 },*/
62 /*{ "ibm-62383_P100-2007", 0xa5 },*/
63 /*{ "ibm-891_P100-1995", 0x20a9 },*/
64 { "ibm-944_P100-1995", 0x20a9 },
65 { "ibm-949_P110-1999", 0x20a9 },
66 { "ibm-1363_P110-1997", 0x20a9 },
67 { "ISO_2022,locale=ko,version=0", 0x20a9 },
68 { "ibm-1088_P100-1995", 0x20a9 }
69};
70
71/*Calls through createConverter */
72U_CAPIextern "C" UConverter* U_EXPORT2
73ucnv_openucnv_open_71 (const char *name,
74 UErrorCode * err)
75{
76 UConverter *r;
77
78 if (err == NULL__null || U_FAILURE (*err)) {
79 return NULL__null;
80 }
81
82 r = ucnv_createConverterucnv_createConverter_71(NULL__null, name, err);
83 return r;
84}
85
86U_CAPIextern "C" UConverter* U_EXPORT2
87ucnv_openPackageucnv_openPackage_71 (const char *packageName, const char *converterName, UErrorCode * err)
88{
89 return ucnv_createConverterFromPackageucnv_createConverterFromPackage_71(packageName, converterName, err);
90}
91
92/*Extracts the UChar* to a char* and calls through createConverter */
93U_CAPIextern "C" UConverter* U_EXPORT2
94ucnv_openUucnv_openU_71 (const UChar * name,
95 UErrorCode * err)
96{
97 char asciiName[UCNV_MAX_CONVERTER_NAME_LENGTH60];
98
99 if (err == NULL__null || U_FAILURE(*err))
100 return NULL__null;
101 if (name == NULL__null)
102 return ucnv_openucnv_open_71 (NULL__null, err);
103 if (u_strlenu_strlen_71(name) >= UCNV_MAX_CONVERTER_NAME_LENGTH60)
104 {
105 *err = U_ILLEGAL_ARGUMENT_ERROR;
106 return NULL__null;
107 }
108 return ucnv_openucnv_open_71(u_austrcpyu_austrcpy_71(asciiName, name), err);
109}
110
111/* Copy the string that is represented by the UConverterPlatform enum
112 * @param platformString An output buffer
113 * @param platform An enum representing a platform
114 * @return the length of the copied string.
115 */
116static int32_t
117ucnv_copyPlatformString(char *platformString, UConverterPlatform pltfrm)
118{
119 switch (pltfrm)
120 {
121 case UCNV_IBM:
122 uprv_strcpy(platformString, "ibm-"):: strcpy(platformString, "ibm-");
123 return 4;
124 case UCNV_UNKNOWN:
125 break;
126 }
127
128 /* default to empty string */
129 *platformString = 0;
130 return 0;
131}
132
133/*Assumes a $platform-#codepage.$CONVERTER_FILE_EXTENSION scheme and calls
134 *through createConverter*/
135U_CAPIextern "C" UConverter* U_EXPORT2
136ucnv_openCCSIDucnv_openCCSID_71 (int32_t codepage,
137 UConverterPlatform platform,
138 UErrorCode * err)
139{
140 char myName[UCNV_MAX_CONVERTER_NAME_LENGTH60];
141 int32_t myNameLen;
142
143 if (err == NULL__null || U_FAILURE (*err))
144 return NULL__null;
145
146 /* ucnv_copyPlatformString could return "ibm-" or "cp" */
147 myNameLen = ucnv_copyPlatformString(myName, platform);
148 T_CString_integerToStringT_CString_integerToString_71(myName + myNameLen, codepage, 10);
149
150 return ucnv_createConverterucnv_createConverter_71(NULL__null, myName, err);
151}
152
153/* Creating a temporary stack-based object that can be used in one thread,
154and created from a converter that is shared across threads.
155*/
156
157U_CAPIextern "C" UConverter* U_EXPORT2
158ucnv_safeCloneucnv_safeClone_71(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status)
159{
160 UConverter *localConverter, *allocatedConverter;
161 int32_t stackBufferSize;
162 int32_t bufferSizeNeeded;
163 UErrorCode cbErr;
164 UConverterToUnicodeArgs toUArgs = {
165 sizeof(UConverterToUnicodeArgs),
166 TRUE1,
167 NULL__null,
168 NULL__null,
169 NULL__null,
170 NULL__null,
171 NULL__null,
172 NULL__null
173 };
174 UConverterFromUnicodeArgs fromUArgs = {
175 sizeof(UConverterFromUnicodeArgs),
176 TRUE1,
177 NULL__null,
178 NULL__null,
179 NULL__null,
180 NULL__null,
181 NULL__null,
182 NULL__null
183 };
184
185 UTRACE_ENTRY_OC(UTRACE_UCNV_CLONE);
186
187 if (status == NULL__null || U_FAILURE(*status)){
188 UTRACE_EXIT_STATUS(status? *status: U_ILLEGAL_ARGUMENT_ERROR);
189 return NULL__null;
190 }
191
192 if (cnv == NULL__null) {
193 *status = U_ILLEGAL_ARGUMENT_ERROR;
194 UTRACE_EXIT_STATUS(*status);
195 return NULL__null;
196 }
197
198 UTRACE_DATA3(UTRACE_OPEN_CLOSE, "clone converter %s at %p into stackBuffer %p",
199 ucnv_getName(cnv, status), cnv, stackBuffer);
200
201 if (cnv->sharedData->impl->safeClone != NULL__null) {
202 /* call the custom safeClone function for sizing */
203 bufferSizeNeeded = 0;
204 cnv->sharedData->impl->safeClone(cnv, NULL__null, &bufferSizeNeeded, status);
205 if (U_FAILURE(*status)) {
206 UTRACE_EXIT_STATUS(*status);
207 return NULL__null;
208 }
209 }
210 else
211 {
212 /* inherent sizing */
213 bufferSizeNeeded = sizeof(UConverter);
214 }
215
216 if (pBufferSize == NULL__null) {
217 stackBufferSize = 1;
218 pBufferSize = &stackBufferSize;
219 } else {
220 stackBufferSize = *pBufferSize;
221 if (stackBufferSize <= 0){ /* 'preflighting' request - set needed size into *pBufferSize */
222 *pBufferSize = bufferSizeNeeded;
223 UTRACE_EXIT_VALUE(bufferSizeNeeded);
224 return NULL__null;
225 }
226 }
227
228 /* Adjust (if necessary) the stackBuffer pointer to be aligned correctly for a UConverter.
229 * TODO(Jira ICU-20736) Redo this using std::align() once g++4.9 compatibility is no longer needed.
230 */
231 if (stackBuffer) {
232 uintptr_t p = reinterpret_cast<uintptr_t>(stackBuffer);
233 uintptr_t aligned_p = (p + alignof(UConverter) - 1) & ~(alignof(UConverter) - 1);
234 ptrdiff_t pointerAdjustment = aligned_p - p;
235 if (bufferSizeNeeded + pointerAdjustment <= stackBufferSize) {
236 stackBuffer = reinterpret_cast<void *>(aligned_p);
237 stackBufferSize -= static_cast<int32_t>(pointerAdjustment);
238 } else {
239 /* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */
240 stackBufferSize = 1;
241 }
242 }
243
244 /* Now, see if we must allocate any memory */
245 if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL__null)
246 {
247 /* allocate one here...*/
248 localConverter = allocatedConverter = (UConverter *) uprv_mallocuprv_malloc_71 (bufferSizeNeeded);
249
250 if(localConverter == NULL__null) {
251 *status = U_MEMORY_ALLOCATION_ERROR;
252 UTRACE_EXIT_STATUS(*status);
253 return NULL__null;
254 }
255 // If pBufferSize was NULL as the input, pBufferSize is set to &stackBufferSize in this function.
256 if (pBufferSize != &stackBufferSize) {
257 *status = U_SAFECLONE_ALLOCATED_WARNING;
258 }
259
260 /* record the fact that memory was allocated */
261 *pBufferSize = bufferSizeNeeded;
262 } else {
263 /* just use the stack buffer */
264 localConverter = (UConverter*) stackBuffer;
265 allocatedConverter = NULL__null;
266 }
267
268 uprv_memset(localConverter, 0, bufferSizeNeeded):: memset(localConverter, 0, bufferSizeNeeded);
269
270 /* Copy initial state */
271 uprv_memcpy(localConverter, cnv, sizeof(UConverter))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(localConverter
, cnv, sizeof(UConverter)); } while (false)
;
272 localConverter->isCopyLocal = localConverter->isExtraLocal = FALSE0;
273
274 /* copy the substitution string */
275 if (cnv->subChars == (uint8_t *)cnv->subUChars) {
276 localConverter->subChars = (uint8_t *)localConverter->subUChars;
277 } else {
278 localConverter->subChars = (uint8_t *)uprv_mallocuprv_malloc_71(UCNV_ERROR_BUFFER_LENGTH32 * U_SIZEOF_UCHAR2);
279 if (localConverter->subChars == NULL__null) {
280 uprv_freeuprv_free_71(allocatedConverter);
281 UTRACE_EXIT_STATUS(*status);
282 return NULL__null;
283 }
284 uprv_memcpy(localConverter->subChars, cnv->subChars, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(localConverter
->subChars, cnv->subChars, 32 * 2); } while (false)
;
285 }
286
287 /* now either call the safeclone fcn or not */
288 if (cnv->sharedData->impl->safeClone != NULL__null) {
289 /* call the custom safeClone function */
290 localConverter = cnv->sharedData->impl->safeClone(cnv, localConverter, pBufferSize, status);
291 }
292
293 if(localConverter==NULL__null || U_FAILURE(*status)) {
294 if (allocatedConverter != NULL__null && allocatedConverter->subChars != (uint8_t *)allocatedConverter->subUChars) {
295 uprv_freeuprv_free_71(allocatedConverter->subChars);
296 }
297 uprv_freeuprv_free_71(allocatedConverter);
298 UTRACE_EXIT_STATUS(*status);
299 return NULL__null;
300 }
301
302 /* increment refcount of shared data if needed */
303 if (cnv->sharedData->isReferenceCounted) {
304 ucnv_incrementRefCountucnv_incrementRefCount_71(cnv->sharedData);
305 }
306
307 if(localConverter == (UConverter*)stackBuffer) {
308 /* we're using user provided data - set to not destroy */
309 localConverter->isCopyLocal = TRUE1;
310 }
311
312 /* allow callback functions to handle any memory allocation */
313 toUArgs.converter = fromUArgs.converter = localConverter;
314 cbErr = U_ZERO_ERROR;
315 cnv->fromCharErrorBehaviour(cnv->toUContext, &toUArgs, NULL__null, 0, UCNV_CLONE, &cbErr);
316 cbErr = U_ZERO_ERROR;
317 cnv->fromUCharErrorBehaviour(cnv->fromUContext, &fromUArgs, NULL__null, 0, 0, UCNV_CLONE, &cbErr);
318
319 UTRACE_EXIT_PTR_STATUS(localConverter, *status);
320 return localConverter;
321}
322
323U_CAPIextern "C" UConverter* U_EXPORT2
324ucnv_cloneucnv_clone_71(const UConverter* cnv, UErrorCode *status)
325{
326 return ucnv_safeCloneucnv_safeClone_71(cnv, nullptr, nullptr, status);
327}
328
329/*Decreases the reference counter in the shared immutable section of the object
330 *and frees the mutable part*/
331
332U_CAPIextern "C" void U_EXPORT2
333ucnv_closeucnv_close_71 (UConverter * converter)
334{
335 UErrorCode errorCode = U_ZERO_ERROR;
336
337 UTRACE_ENTRY_OC(UTRACE_UCNV_CLOSE);
338
339 if (converter == NULL__null)
340 {
341 UTRACE_EXIT();
342 return;
343 }
344
345 UTRACE_DATA3(UTRACE_OPEN_CLOSE, "close converter %s at %p, isCopyLocal=%b",
346 ucnv_getName(converter, &errorCode), converter, converter->isCopyLocal);
347
348 /* In order to speed up the close, only call the callbacks when they have been changed.
349 This performance check will only work when the callbacks are set within a shared library
350 or from user code that statically links this code. */
351 /* first, notify the callback functions that the converter is closed */
352 if (converter->fromCharErrorBehaviour != UCNV_TO_U_DEFAULT_CALLBACK((UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE_71)) {
353 UConverterToUnicodeArgs toUArgs = {
354 sizeof(UConverterToUnicodeArgs),
355 TRUE1,
356 NULL__null,
357 NULL__null,
358 NULL__null,
359 NULL__null,
360 NULL__null,
361 NULL__null
362 };
363
364 toUArgs.converter = converter;
365 errorCode = U_ZERO_ERROR;
366 converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL__null, 0, UCNV_CLOSE, &errorCode);
367 }
368 if (converter->fromUCharErrorBehaviour != UCNV_FROM_U_DEFAULT_CALLBACK((UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE_71
)
) {
369 UConverterFromUnicodeArgs fromUArgs = {
370 sizeof(UConverterFromUnicodeArgs),
371 TRUE1,
372 NULL__null,
373 NULL__null,
374 NULL__null,
375 NULL__null,
376 NULL__null,
377 NULL__null
378 };
379 fromUArgs.converter = converter;
380 errorCode = U_ZERO_ERROR;
381 converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL__null, 0, 0, UCNV_CLOSE, &errorCode);
382 }
383
384 if (converter->sharedData->impl->close != NULL__null) {
385 converter->sharedData->impl->close(converter);
386 }
387
388 if (converter->subChars != (uint8_t *)converter->subUChars) {
389 uprv_freeuprv_free_71(converter->subChars);
390 }
391
392 if (converter->sharedData->isReferenceCounted) {
393 ucnv_unloadSharedDataIfReadyucnv_unloadSharedDataIfReady_71(converter->sharedData);
394 }
395
396 if(!converter->isCopyLocal){
397 uprv_freeuprv_free_71(converter);
398 }
399
400 UTRACE_EXIT();
401}
402
403/*returns a single Name from the list, will return NULL if out of bounds
404 */
405U_CAPIextern "C" const char* U_EXPORT2
406ucnv_getAvailableNameucnv_getAvailableName_71 (int32_t n)
407{
408 if (0 <= n && n <= 0xffff) {
409 UErrorCode err = U_ZERO_ERROR;
410 const char *name = ucnv_bld_getAvailableConverterucnv_bld_getAvailableConverter_71((uint16_t)n, &err);
411 if (U_SUCCESS(err)) {
412 return name;
413 }
414 }
415 return NULL__null;
416}
417
418U_CAPIextern "C" int32_t U_EXPORT2
419ucnv_countAvailableucnv_countAvailable_71 ()
420{
421 UErrorCode err = U_ZERO_ERROR;
422 return ucnv_bld_countAvailableConvertersucnv_bld_countAvailableConverters_71(&err);
423}
424
425U_CAPIextern "C" void U_EXPORT2
426ucnv_getSubstCharsucnv_getSubstChars_71 (const UConverter * converter,
427 char *mySubChar,
428 int8_t * len,
429 UErrorCode * err)
430{
431 if (U_FAILURE (*err))
432 return;
433
434 if (converter->subCharLen <= 0) {
435 /* Unicode string or empty string from ucnv_setSubstString(). */
436 *len = 0;
437 return;
438 }
439
440 if (*len < converter->subCharLen) /*not enough space in subChars */
441 {
442 *err = U_INDEX_OUTOFBOUNDS_ERROR;
443 return;
444 }
445
446 uprv_memcpy (mySubChar, converter->subChars, converter->subCharLen)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(mySubChar
, converter->subChars, converter->subCharLen); } while (
false)
; /*fills in the subchars */
447 *len = converter->subCharLen; /*store # of bytes copied to buffer */
448}
449
450U_CAPIextern "C" void U_EXPORT2
451ucnv_setSubstCharsucnv_setSubstChars_71 (UConverter * converter,
452 const char *mySubChar,
453 int8_t len,
454 UErrorCode * err)
455{
456 if (U_FAILURE (*err))
457 return;
458
459 /*Makes sure that the subChar is within the codepages char length boundaries */
460 if ((len > converter->sharedData->staticData->maxBytesPerChar)
461 || (len < converter->sharedData->staticData->minBytesPerChar))
462 {
463 *err = U_ILLEGAL_ARGUMENT_ERROR;
464 return;
465 }
466
467 uprv_memcpy (converter->subChars, mySubChar, len)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(converter
->subChars, mySubChar, len); } while (false)
; /*copies the subchars */
468 converter->subCharLen = len; /*sets the new len */
469
470 /*
471 * There is currently (2001Feb) no separate API to set/get subChar1.
472 * In order to always have subChar written after it is explicitly set,
473 * we set subChar1 to 0.
474 */
475 converter->subChar1 = 0;
476
477 return;
478}
479
480U_CAPIextern "C" void U_EXPORT2
481ucnv_setSubstStringucnv_setSubstString_71(UConverter *cnv,
482 const UChar *s,
483 int32_t length,
484 UErrorCode *err) {
485 alignas(UConverter) char cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE1024];
486 char chars[UCNV_ERROR_BUFFER_LENGTH32];
487
488 UConverter *clone;
489 uint8_t *subChars;
490 int32_t cloneSize, length8;
491
492 /* Let the following functions check all arguments. */
493 cloneSize = sizeof(cloneBuffer);
494 clone = ucnv_safeCloneucnv_safeClone_71(cnv, cloneBuffer, &cloneSize, err);
495 ucnv_setFromUCallBackucnv_setFromUCallBack_71(clone, UCNV_FROM_U_CALLBACK_STOPUCNV_FROM_U_CALLBACK_STOP_71, NULL__null, NULL__null, NULL__null, err);
496 length8 = ucnv_fromUCharsucnv_fromUChars_71(clone, chars, (int32_t)sizeof(chars), s, length, err);
497 ucnv_closeucnv_close_71(clone);
498 if (U_FAILURE(*err)) {
499 return;
500 }
501
502 if (cnv->sharedData->impl->writeSub == NULL__null
503#if !UCONFIG_NO_LEGACY_CONVERSION0
504 || (cnv->sharedData->staticData->conversionType == UCNV_MBCS &&
505 ucnv_MBCSGetTypeucnv_MBCSGetType_71(cnv) != UCNV_EBCDIC_STATEFUL)
506#endif
507 ) {
508 /* The converter is not stateful. Store the charset bytes as a fixed string. */
509 subChars = (uint8_t *)chars;
510 } else {
511 /*
512 * The converter has a non-default writeSub() function, indicating
513 * that it is stateful.
514 * Store the Unicode string for on-the-fly conversion for correct
515 * state handling.
516 */
517 if (length > UCNV_ERROR_BUFFER_LENGTH32) {
518 /*
519 * Should not occur. The converter should output at least one byte
520 * per UChar, which means that ucnv_fromUChars() should catch all
521 * overflows.
522 */
523 *err = U_BUFFER_OVERFLOW_ERROR;
524 return;
525 }
526 subChars = (uint8_t *)s;
527 if (length < 0) {
528 length = u_strlenu_strlen_71(s);
529 }
530 length8 = length * U_SIZEOF_UCHAR2;
531 }
532
533 /*
534 * For storing the substitution string, select either the small buffer inside
535 * UConverter or allocate a subChars buffer.
536 */
537 if (length8 > UCNV_MAX_SUBCHAR_LEN4) {
538 /* Use a separate buffer for the string. Outside UConverter to not make it too large. */
539 if (cnv->subChars == (uint8_t *)cnv->subUChars) {
540 /* Allocate a new buffer for the string. */
541 cnv->subChars = (uint8_t *)uprv_mallocuprv_malloc_71(UCNV_ERROR_BUFFER_LENGTH32 * U_SIZEOF_UCHAR2);
542 if (cnv->subChars == NULL__null) {
543 cnv->subChars = (uint8_t *)cnv->subUChars;
544 *err = U_MEMORY_ALLOCATION_ERROR;
545 return;
546 }
547 uprv_memset(cnv->subChars, 0, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR):: memset(cnv->subChars, 0, 32 * 2);
548 }
549 }
550
551 /* Copy the substitution string into the UConverter or its subChars buffer. */
552 if (length8 == 0) {
553 cnv->subCharLen = 0;
554 } else {
555 uprv_memcpy(cnv->subChars, subChars, length8)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(cnv->subChars
, subChars, length8); } while (false)
;
556 if (subChars == (uint8_t *)chars) {
557 cnv->subCharLen = (int8_t)length8;
558 } else /* subChars == s */ {
559 cnv->subCharLen = (int8_t)-length;
560 }
561 }
562
563 /* See comment in ucnv_setSubstChars(). */
564 cnv->subChar1 = 0;
565}
566
567/*resets the internal states of a converter
568 *goal : have the same behaviour than a freshly created converter
569 */
570static void _reset(UConverter *converter, UConverterResetChoice choice,
571 UBool callCallback) {
572 if(converter == NULL__null) {
573 return;
574 }
575
576 if(callCallback) {
577 /* first, notify the callback functions that the converter is reset */
578 UErrorCode errorCode;
579
580 if(choice<=UCNV_RESET_TO_UNICODE && converter->fromCharErrorBehaviour != UCNV_TO_U_DEFAULT_CALLBACK((UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE_71)) {
581 UConverterToUnicodeArgs toUArgs = {
582 sizeof(UConverterToUnicodeArgs),
583 TRUE1,
584 NULL__null,
585 NULL__null,
586 NULL__null,
587 NULL__null,
588 NULL__null,
589 NULL__null
590 };
591 toUArgs.converter = converter;
592 errorCode = U_ZERO_ERROR;
593 converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL__null, 0, UCNV_RESET, &errorCode);
594 }
595 if(choice!=UCNV_RESET_TO_UNICODE && converter->fromUCharErrorBehaviour != UCNV_FROM_U_DEFAULT_CALLBACK((UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE_71
)
) {
596 UConverterFromUnicodeArgs fromUArgs = {
597 sizeof(UConverterFromUnicodeArgs),
598 TRUE1,
599 NULL__null,
600 NULL__null,
601 NULL__null,
602 NULL__null,
603 NULL__null,
604 NULL__null
605 };
606 fromUArgs.converter = converter;
607 errorCode = U_ZERO_ERROR;
608 converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL__null, 0, 0, UCNV_RESET, &errorCode);
609 }
610 }
611
612 /* now reset the converter itself */
613 if(choice<=UCNV_RESET_TO_UNICODE) {
614 converter->toUnicodeStatus = converter->sharedData->toUnicodeStatus;
615 converter->mode = 0;
616 converter->toULength = 0;
617 converter->invalidCharLength = converter->UCharErrorBufferLength = 0;
618 converter->preToULength = 0;
619 }
620 if(choice!=UCNV_RESET_TO_UNICODE) {
621 converter->fromUnicodeStatus = 0;
622 converter->fromUChar32 = 0;
623 converter->invalidUCharLength = converter->charErrorBufferLength = 0;
624 converter->preFromUFirstCP = U_SENTINEL(-1);
625 converter->preFromULength = 0;
626 }
627
628 if (converter->sharedData->impl->reset != NULL__null) {
629 /* call the custom reset function */
630 converter->sharedData->impl->reset(converter, choice);
631 }
632}
633
634U_CAPIextern "C" void U_EXPORT2
635ucnv_resetucnv_reset_71(UConverter *converter)
636{
637 _reset(converter, UCNV_RESET_BOTH, TRUE1);
638}
639
640U_CAPIextern "C" void U_EXPORT2
641ucnv_resetToUnicodeucnv_resetToUnicode_71(UConverter *converter)
642{
643 _reset(converter, UCNV_RESET_TO_UNICODE, TRUE1);
644}
645
646U_CAPIextern "C" void U_EXPORT2
647ucnv_resetFromUnicodeucnv_resetFromUnicode_71(UConverter *converter)
648{
649 _reset(converter, UCNV_RESET_FROM_UNICODE, TRUE1);
650}
651
652U_CAPIextern "C" int8_t U_EXPORT2
653ucnv_getMaxCharSizeucnv_getMaxCharSize_71 (const UConverter * converter)
654{
655 return converter->maxBytesPerUChar;
656}
657
658
659U_CAPIextern "C" int8_t U_EXPORT2
660ucnv_getMinCharSizeucnv_getMinCharSize_71 (const UConverter * converter)
661{
662 return converter->sharedData->staticData->minBytesPerChar;
663}
664
665U_CAPIextern "C" const char* U_EXPORT2
666ucnv_getNameucnv_getName_71 (const UConverter * converter, UErrorCode * err)
667
668{
669 if (U_FAILURE (*err))
670 return NULL__null;
671 if(converter->sharedData->impl->getName){
672 const char* temp= converter->sharedData->impl->getName(converter);
673 if(temp)
674 return temp;
675 }
676 return converter->sharedData->staticData->name;
677}
678
679U_CAPIextern "C" int32_t U_EXPORT2
680ucnv_getCCSIDucnv_getCCSID_71(const UConverter * converter,
681 UErrorCode * err)
682{
683 int32_t ccsid;
684 if (U_FAILURE (*err))
685 return -1;
686
687 ccsid = converter->sharedData->staticData->codepage;
688 if (ccsid == 0) {
689 /* Rare case. This is for cases like gb18030,
690 which doesn't have an IBM canonical name, but does have an IBM alias. */
691 const char *standardName = ucnv_getStandardNameucnv_getStandardName_71(ucnv_getNameucnv_getName_71(converter, err), "IBM", err);
692 if (U_SUCCESS(*err) && standardName) {
693 const char *ccsidStr = uprv_strchr(standardName, '-'):: strchr(standardName, '-');
694 if (ccsidStr) {
695 ccsid = (int32_t)atol(ccsidStr+1); /* +1 to skip '-' */
696 }
697 }
698 }
699 return ccsid;
700}
701
702
703U_CAPIextern "C" UConverterPlatform U_EXPORT2
704ucnv_getPlatformucnv_getPlatform_71 (const UConverter * converter,
705 UErrorCode * err)
706{
707 if (U_FAILURE (*err))
708 return UCNV_UNKNOWN;
709
710 return (UConverterPlatform)converter->sharedData->staticData->platform;
711}
712
713U_CAPIextern "C" void U_EXPORT2
714 ucnv_getToUCallBackucnv_getToUCallBack_71 (const UConverter * converter,
715 UConverterToUCallback *action,
716 const void **context)
717{
718 *action = converter->fromCharErrorBehaviour;
719 *context = converter->toUContext;
720}
721
722U_CAPIextern "C" void U_EXPORT2
723 ucnv_getFromUCallBackucnv_getFromUCallBack_71 (const UConverter * converter,
724 UConverterFromUCallback *action,
725 const void **context)
726{
727 *action = converter->fromUCharErrorBehaviour;
728 *context = converter->fromUContext;
729}
730
731U_CAPIextern "C" void U_EXPORT2
732ucnv_setToUCallBackucnv_setToUCallBack_71 (UConverter * converter,
733 UConverterToUCallback newAction,
734 const void* newContext,
735 UConverterToUCallback *oldAction,
736 const void** oldContext,
737 UErrorCode * err)
738{
739 if (U_FAILURE (*err))
740 return;
741 if (oldAction) *oldAction = converter->fromCharErrorBehaviour;
742 converter->fromCharErrorBehaviour = newAction;
743 if (oldContext) *oldContext = converter->toUContext;
744 converter->toUContext = newContext;
745}
746
747U_CAPIextern "C" void U_EXPORT2
748ucnv_setFromUCallBackucnv_setFromUCallBack_71 (UConverter * converter,
749 UConverterFromUCallback newAction,
750 const void* newContext,
751 UConverterFromUCallback *oldAction,
752 const void** oldContext,
753 UErrorCode * err)
754{
755 if (U_FAILURE (*err))
756 return;
757 if (oldAction) *oldAction = converter->fromUCharErrorBehaviour;
758 converter->fromUCharErrorBehaviour = newAction;
759 if (oldContext) *oldContext = converter->fromUContext;
760 converter->fromUContext = newContext;
761}
762
763static void
764_updateOffsets(int32_t *offsets, int32_t length,
765 int32_t sourceIndex, int32_t errorInputLength) {
766 int32_t *limit;
767 int32_t delta, offset;
768
769 if(sourceIndex>=0) {
770 /*
771 * adjust each offset by adding the previous sourceIndex
772 * minus the length of the input sequence that caused an
773 * error, if any
774 */
775 delta=sourceIndex-errorInputLength;
776 } else {
777 /*
778 * set each offset to -1 because this conversion function
779 * does not handle offsets
780 */
781 delta=-1;
782 }
783
784 limit=offsets+length;
785 if(delta==0) {
786 /* most common case, nothing to do */
787 } else if(delta>0) {
788 /* add the delta to each offset (but not if the offset is <0) */
789 while(offsets<limit) {
790 offset=*offsets;
791 if(offset>=0) {
792 *offsets=offset+delta;
793 }
794 ++offsets;
795 }
796 } else /* delta<0 */ {
797 /*
798 * set each offset to -1 because this conversion function
799 * does not handle offsets
800 * or the error input sequence started in a previous buffer
801 */
802 while(offsets<limit) {
803 *offsets++=-1;
804 }
805 }
806}
807
808/* ucnv_fromUnicode --------------------------------------------------------- */
809
810/*
811 * Implementation note for m:n conversions
812 *
813 * While collecting source units to find the longest match for m:n conversion,
814 * some source units may need to be stored for a partial match.
815 * When a second buffer does not yield a match on all of the previously stored
816 * source units, then they must be "replayed", i.e., fed back into the converter.
817 *
818 * The code relies on the fact that replaying will not nest -
819 * converting a replay buffer will not result in a replay.
820 * This is because a replay is necessary only after the _continuation_ of a
821 * partial match failed, but a replay buffer is converted as a whole.
822 * It may result in some of its units being stored again for a partial match,
823 * but there will not be a continuation _during_ the replay which could fail.
824 *
825 * It is conceivable that a callback function could call the converter
826 * recursively in a way that causes another replay to be stored, but that
827 * would be an error in the callback function.
828 * Such violations will cause assertion failures in a debug build,
829 * and wrong output, but they will not cause a crash.
830 */
831
832static void
833_fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) {
834 UConverterFromUnicode fromUnicode;
835 UConverter *cnv;
836 const UChar *s;
837 char *t;
838 int32_t *offsets;
839 int32_t sourceIndex;
840 int32_t errorInputLength;
841 UBool converterSawEndOfInput, calledCallback;
842
843 /* variables for m:n conversion */
844 UChar replay[UCNV_EXT_MAX_UCHARS19];
845 const UChar *realSource, *realSourceLimit;
846 int32_t realSourceIndex;
847 UBool realFlush;
848
849 cnv=pArgs->converter;
850 s=pArgs->source;
851 t=pArgs->target;
852 offsets=pArgs->offsets;
853
854 /* get the converter implementation function */
855 sourceIndex=0;
856 if(offsets==NULL__null) {
857 fromUnicode=cnv->sharedData->impl->fromUnicode;
858 } else {
859 fromUnicode=cnv->sharedData->impl->fromUnicodeWithOffsets;
860 if(fromUnicode==NULL__null) {
861 /* there is no WithOffsets implementation */
862 fromUnicode=cnv->sharedData->impl->fromUnicode;
863 /* we will write -1 for each offset */
864 sourceIndex=-1;
865 }
866 }
867
868 if(cnv->preFromULength>=0) {
869 /* normal mode */
870 realSource=NULL__null;
871
872 /* avoid compiler warnings - not otherwise necessary, and the values do not matter */
873 realSourceLimit=NULL__null;
874 realFlush=FALSE0;
875 realSourceIndex=0;
876 } else {
877 /*
878 * Previous m:n conversion stored source units from a partial match
879 * and failed to consume all of them.
880 * We need to "replay" them from a temporary buffer and convert them first.
881 */
882 realSource=pArgs->source;
883 realSourceLimit=pArgs->sourceLimit;
884 realFlush=pArgs->flush;
885 realSourceIndex=sourceIndex;
886
887 uprv_memcpy(replay, cnv->preFromU, -cnv->preFromULength*U_SIZEOF_UCHAR)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(replay, cnv
->preFromU, -cnv->preFromULength*2); } while (false)
;
888 pArgs->source=replay;
889 pArgs->sourceLimit=replay-cnv->preFromULength;
890 pArgs->flush=FALSE0;
891 sourceIndex=-1;
892
893 cnv->preFromULength=0;
894 }
895
896 /*
897 * loop for conversion and error handling
898 *
899 * loop {
900 * convert
901 * loop {
902 * update offsets
903 * handle end of input
904 * handle errors/call callback
905 * }
906 * }
907 */
908 for(;;) {
909 if(U_SUCCESS(*err)) {
910 /* convert */
911 fromUnicode(pArgs, err);
912
913 /*
914 * set a flag for whether the converter
915 * successfully processed the end of the input
916 *
917 * need not check cnv->preFromULength==0 because a replay (<0) will cause
918 * s<sourceLimit before converterSawEndOfInput is checked
919 */
920 converterSawEndOfInput=
921 (UBool)(U_SUCCESS(*err) &&
922 pArgs->flush && pArgs->source==pArgs->sourceLimit &&
923 cnv->fromUChar32==0);
924 } else {
925 /* handle error from ucnv_convertEx() */
926 converterSawEndOfInput=FALSE0;
927 }
928
929 /* no callback called yet for this iteration */
930 calledCallback=FALSE0;
931
932 /* no sourceIndex adjustment for conversion, only for callback output */
933 errorInputLength=0;
934
935 /*
936 * loop for offsets and error handling
937 *
938 * iterates at most 3 times:
939 * 1. to clean up after the conversion function
940 * 2. after the callback
941 * 3. after the callback again if there was truncated input
942 */
943 for(;;) {
944 /* update offsets if we write any */
945 if(offsets!=NULL__null) {
946 int32_t length=(int32_t)(pArgs->target-t);
947 if(length>0) {
948 _updateOffsets(offsets, length, sourceIndex, errorInputLength);
949
950 /*
951 * if a converter handles offsets and updates the offsets
952 * pointer at the end, then pArgs->offset should not change
953 * here;
954 * however, some converters do not handle offsets at all
955 * (sourceIndex<0) or may not update the offsets pointer
956 */
957 pArgs->offsets=offsets+=length;
958 }
959
960 if(sourceIndex>=0) {
961 sourceIndex+=(int32_t)(pArgs->source-s);
962 }
963 }
964
965 if(cnv->preFromULength<0) {
966 /*
967 * switch the source to new replay units (cannot occur while replaying)
968 * after offset handling and before end-of-input and callback handling
969 */
970 if(realSource==NULL__null) {
971 realSource=pArgs->source;
972 realSourceLimit=pArgs->sourceLimit;
973 realFlush=pArgs->flush;
974 realSourceIndex=sourceIndex;
975
976 uprv_memcpy(replay, cnv->preFromU, -cnv->preFromULength*U_SIZEOF_UCHAR)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(replay, cnv
->preFromU, -cnv->preFromULength*2); } while (false)
;
977 pArgs->source=replay;
978 pArgs->sourceLimit=replay-cnv->preFromULength;
979 pArgs->flush=FALSE0;
980 if((sourceIndex+=cnv->preFromULength)<0) {
981 sourceIndex=-1;
982 }
983
984 cnv->preFromULength=0;
985 } else {
986 /* see implementation note before _fromUnicodeWithCallback() */
987 U_ASSERT(realSource==NULL)(void)0;
988 *err=U_INTERNAL_PROGRAM_ERROR;
989 }
990 }
991
992 /* update pointers */
993 s=pArgs->source;
994 t=pArgs->target;
995
996 if(U_SUCCESS(*err)) {
997 if(s<pArgs->sourceLimit) {
998 /*
999 * continue with the conversion loop while there is still input left
1000 * (continue converting by breaking out of only the inner loop)
1001 */
1002 break;
1003 } else if(realSource!=NULL__null) {
1004 /* switch back from replaying to the real source and continue */
1005 pArgs->source=realSource;
1006 pArgs->sourceLimit=realSourceLimit;
1007 pArgs->flush=realFlush;
1008 sourceIndex=realSourceIndex;
1009
1010 realSource=NULL__null;
1011 break;
1012 } else if(pArgs->flush && cnv->fromUChar32!=0) {
1013 /*
1014 * the entire input stream is consumed
1015 * and there is a partial, truncated input sequence left
1016 */
1017
1018 /* inject an error and continue with callback handling */
1019 *err=U_TRUNCATED_CHAR_FOUND;
1020 calledCallback=FALSE0; /* new error condition */
1021 } else {
1022 /* input consumed */
1023 if(pArgs->flush) {
1024 /*
1025 * return to the conversion loop once more if the flush
1026 * flag is set and the conversion function has not
1027 * successfully processed the end of the input yet
1028 *
1029 * (continue converting by breaking out of only the inner loop)
1030 */
1031 if(!converterSawEndOfInput) {
1032 break;
1033 }
1034
1035 /* reset the converter without calling the callback function */
1036 _reset(cnv, UCNV_RESET_FROM_UNICODE, FALSE0);
1037 }
1038
1039 /* done successfully */
1040 return;
1041 }
1042 }
1043
1044 /* U_FAILURE(*err) */
1045 {
1046 UErrorCode e;
1047
1048 if( calledCallback ||
1049 (e=*err)==U_BUFFER_OVERFLOW_ERROR ||
1050 (e!=U_INVALID_CHAR_FOUND &&
1051 e!=U_ILLEGAL_CHAR_FOUND &&
1052 e!=U_TRUNCATED_CHAR_FOUND)
1053 ) {
1054 /*
1055 * the callback did not or cannot resolve the error:
1056 * set output pointers and return
1057 *
1058 * the check for buffer overflow is redundant but it is
1059 * a high-runner case and hopefully documents the intent
1060 * well
1061 *
1062 * if we were replaying, then the replay buffer must be
1063 * copied back into the UConverter
1064 * and the real arguments must be restored
1065 */
1066 if(realSource!=NULL__null) {
1067 int32_t length;
1068
1069 U_ASSERT(cnv->preFromULength==0)(void)0;
1070
1071 length=(int32_t)(pArgs->sourceLimit-pArgs->source);
1072 if(length>0) {
1073 u_memcpyu_memcpy_71(cnv->preFromU, pArgs->source, length);
1074 cnv->preFromULength=(int8_t)-length;
1075 }
1076
1077 pArgs->source=realSource;
1078 pArgs->sourceLimit=realSourceLimit;
1079 pArgs->flush=realFlush;
1080 }
1081
1082 return;
1083 }
1084 }
1085
1086 /* callback handling */
1087 {
1088 UChar32 codePoint;
1089
1090 /* get and write the code point */
1091 codePoint=cnv->fromUChar32;
1092 errorInputLength=0;
1093 U16_APPEND_UNSAFE(cnv->invalidUCharBuffer, errorInputLength, codePoint)do { if((uint32_t)(codePoint)<=0xffff) { (cnv->invalidUCharBuffer
)[(errorInputLength)++]=(uint16_t)(codePoint); } else { (cnv->
invalidUCharBuffer)[(errorInputLength)++]=(uint16_t)(((codePoint
)>>10)+0xd7c0); (cnv->invalidUCharBuffer)[(errorInputLength
)++]=(uint16_t)(((codePoint)&0x3ff)|0xdc00); } } while (false
)
;
1094 cnv->invalidUCharLength=(int8_t)errorInputLength;
1095
1096 /* set the converter state to deal with the next character */
1097 cnv->fromUChar32=0;
1098
1099 /* call the callback function */
1100 cnv->fromUCharErrorBehaviour(cnv->fromUContext, pArgs,
1101 cnv->invalidUCharBuffer, errorInputLength, codePoint,
1102 *err==U_INVALID_CHAR_FOUND ? UCNV_UNASSIGNED : UCNV_ILLEGAL,
1103 err);
1104 }
1105
1106 /*
1107 * loop back to the offset handling
1108 *
1109 * this flag will indicate after offset handling
1110 * that a callback was called;
1111 * if the callback did not resolve the error, then we return
1112 */
1113 calledCallback=TRUE1;
1114 }
1115 }
1116}
1117
1118/*
1119 * Output the fromUnicode overflow buffer.
1120 * Call this function if(cnv->charErrorBufferLength>0).
1121 * @return TRUE if overflow
1122 */
1123static UBool
1124ucnv_outputOverflowFromUnicode(UConverter *cnv,
1125 char **target, const char *targetLimit,
1126 int32_t **pOffsets,
1127 UErrorCode *err) {
1128 int32_t *offsets;
1129 char *overflow, *t;
1130 int32_t i, length;
1131
1132 t=*target;
1133 if(pOffsets!=NULL__null) {
1134 offsets=*pOffsets;
1135 } else {
1136 offsets=NULL__null;
1137 }
1138
1139 overflow=(char *)cnv->charErrorBuffer;
1140 length=cnv->charErrorBufferLength;
1141 i=0;
1142 while(i<length) {
1143 if(t==targetLimit) {
1144 /* the overflow buffer contains too much, keep the rest */
1145 int32_t j=0;
1146
1147 do {
1148 overflow[j++]=overflow[i++];
1149 } while(i<length);
1150
1151 cnv->charErrorBufferLength=(int8_t)j;
1152 *target=t;
1153 if(offsets!=NULL__null) {
1154 *pOffsets=offsets;
1155 }
1156 *err=U_BUFFER_OVERFLOW_ERROR;
1157 return TRUE1;
1158 }
1159
1160 /* copy the overflow contents to the target */
1161 *t++=overflow[i++];
1162 if(offsets!=NULL__null) {
1163 *offsets++=-1; /* no source index available for old output */
1164 }
1165 }
1166
1167 /* the overflow buffer is completely copied to the target */
1168 cnv->charErrorBufferLength=0;
1169 *target=t;
1170 if(offsets!=NULL__null) {
1171 *pOffsets=offsets;
1172 }
1173 return FALSE0;
1174}
1175
1176U_CAPIextern "C" void U_EXPORT2
1177ucnv_fromUnicodeucnv_fromUnicode_71(UConverter *cnv,
1178 char **target, const char *targetLimit,
1179 const UChar **source, const UChar *sourceLimit,
1180 int32_t *offsets,
1181 UBool flush,
1182 UErrorCode *err) {
1183 UConverterFromUnicodeArgs args;
1184 const UChar *s;
1185 char *t;
1186
1187 /* check parameters */
1188 if(err==NULL__null || U_FAILURE(*err)) {
1189 return;
1190 }
1191
1192 if(cnv==NULL__null || target==NULL__null || source==NULL__null) {
1193 *err=U_ILLEGAL_ARGUMENT_ERROR;
1194 return;
1195 }
1196
1197 s=*source;
1198 t=*target;
1199
1200 if ((const void *)U_MAX_PTR(sourceLimit)((void *)(((uintptr_t)(sourceLimit)+0x7fffffffu) > (uintptr_t
)(sourceLimit) ? ((uintptr_t)(sourceLimit)+0x7fffffffu) : (uintptr_t
)-1))
== (const void *)sourceLimit) {
1201 /*
1202 Prevent code from going into an infinite loop in case we do hit this
1203 limit. The limit pointer is expected to be on a UChar * boundary.
1204 This also prevents the next argument check from failing.
1205 */
1206 sourceLimit = (const UChar *)(((const char *)sourceLimit) - 1);
1207 }
1208
1209 /*
1210 * All these conditions should never happen.
1211 *
1212 * 1) Make sure that the limits are >= to the address source or target
1213 *
1214 * 2) Make sure that the buffer sizes do not exceed the number range for
1215 * int32_t because some functions use the size (in units or bytes)
1216 * rather than comparing pointers, and because offsets are int32_t values.
1217 *
1218 * size_t is guaranteed to be unsigned and large enough for the job.
1219 *
1220 * Return with an error instead of adjusting the limits because we would
1221 * not be able to maintain the semantics that either the source must be
1222 * consumed or the target filled (unless an error occurs).
1223 * An adjustment would be targetLimit=t+0x7fffffff; for example.
1224 *
1225 * 3) Make sure that the user didn't incorrectly cast a UChar * pointer
1226 * to a char * pointer and provide an incomplete UChar code unit.
1227 */
1228 if (sourceLimit<s || targetLimit<t ||
1229 ((size_t)(sourceLimit-s)>(size_t)0x3fffffff && sourceLimit>s) ||
1230 ((size_t)(targetLimit-t)>(size_t)0x7fffffff && targetLimit>t) ||
1231 (((const char *)sourceLimit-(const char *)s) & 1) != 0)
1232 {
1233 *err=U_ILLEGAL_ARGUMENT_ERROR;
1234 return;
1235 }
1236
1237 /* output the target overflow buffer */
1238 if( cnv->charErrorBufferLength>0 &&
1239 ucnv_outputOverflowFromUnicode(cnv, target, targetLimit, &offsets, err)
1240 ) {
1241 /* U_BUFFER_OVERFLOW_ERROR */
1242 return;
1243 }
1244 /* *target may have moved, therefore stop using t */
1245
1246 if(!flush && s==sourceLimit && cnv->preFromULength>=0) {
1247 /* the overflow buffer is emptied and there is no new input: we are done */
1248 return;
1249 }
1250
1251 /*
1252 * Do not simply return with a buffer overflow error if
1253 * !flush && t==targetLimit
1254 * because it is possible that the source will not generate any output.
1255 * For example, the skip callback may be called;
1256 * it does not output anything.
1257 */
1258
1259 /* prepare the converter arguments */
1260 args.converter=cnv;
1261 args.flush=flush;
1262 args.offsets=offsets;
1263 args.source=s;
1264 args.sourceLimit=sourceLimit;
1265 args.target=*target;
1266 args.targetLimit=targetLimit;
1267 args.size=sizeof(args);
1268
1269 _fromUnicodeWithCallback(&args, err);
1270
1271 *source=args.source;
1272 *target=args.target;
1273}
1274
1275/* ucnv_toUnicode() --------------------------------------------------------- */
1276
1277static void
1278_toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) {
1279 UConverterToUnicode toUnicode;
1280 UConverter *cnv;
1281 const char *s;
1282 UChar *t;
1283 int32_t *offsets;
1284 int32_t sourceIndex;
1285 int32_t errorInputLength;
1286 UBool converterSawEndOfInput, calledCallback;
1287
1288 /* variables for m:n conversion */
1289 char replay[UCNV_EXT_MAX_BYTES0x1f];
1290 const char *realSource, *realSourceLimit;
1291 int32_t realSourceIndex;
1292 UBool realFlush;
1293
1294 cnv=pArgs->converter;
1295 s=pArgs->source;
1296 t=pArgs->target;
1297 offsets=pArgs->offsets;
1298
1299 /* get the converter implementation function */
1300 sourceIndex=0;
1301 if(offsets==NULL__null) {
1302 toUnicode=cnv->sharedData->impl->toUnicode;
1303 } else {
1304 toUnicode=cnv->sharedData->impl->toUnicodeWithOffsets;
1305 if(toUnicode==NULL__null) {
1306 /* there is no WithOffsets implementation */
1307 toUnicode=cnv->sharedData->impl->toUnicode;
1308 /* we will write -1 for each offset */
1309 sourceIndex=-1;
1310 }
1311 }
1312
1313 if(cnv->preToULength>=0) {
1314 /* normal mode */
1315 realSource=NULL__null;
1316
1317 /* avoid compiler warnings - not otherwise necessary, and the values do not matter */
1318 realSourceLimit=NULL__null;
1319 realFlush=FALSE0;
1320 realSourceIndex=0;
1321 } else {
1322 /*
1323 * Previous m:n conversion stored source units from a partial match
1324 * and failed to consume all of them.
1325 * We need to "replay" them from a temporary buffer and convert them first.
1326 */
1327 realSource=pArgs->source;
1328 realSourceLimit=pArgs->sourceLimit;
1329 realFlush=pArgs->flush;
1330 realSourceIndex=sourceIndex;
1331
1332 uprv_memcpy(replay, cnv->preToU, -cnv->preToULength)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(replay, cnv
->preToU, -cnv->preToULength); } while (false)
;
1333 pArgs->source=replay;
1334 pArgs->sourceLimit=replay-cnv->preToULength;
1335 pArgs->flush=FALSE0;
1336 sourceIndex=-1;
1337
1338 cnv->preToULength=0;
1339 }
1340
1341 /*
1342 * loop for conversion and error handling
1343 *
1344 * loop {
1345 * convert
1346 * loop {
1347 * update offsets
1348 * handle end of input
1349 * handle errors/call callback
1350 * }
1351 * }
1352 */
1353 for(;;) {
1354 if(U_SUCCESS(*err)) {
1355 /* convert */
1356 toUnicode(pArgs, err);
1357
1358 /*
1359 * set a flag for whether the converter
1360 * successfully processed the end of the input
1361 *
1362 * need not check cnv->preToULength==0 because a replay (<0) will cause
1363 * s<sourceLimit before converterSawEndOfInput is checked
1364 */
1365 converterSawEndOfInput=
1366 (UBool)(U_SUCCESS(*err) &&
1367 pArgs->flush && pArgs->source==pArgs->sourceLimit &&
1368 cnv->toULength==0);
1369 } else {
1370 /* handle error from getNextUChar() or ucnv_convertEx() */
1371 converterSawEndOfInput=FALSE0;
1372 }
1373
1374 /* no callback called yet for this iteration */
1375 calledCallback=FALSE0;
1376
1377 /* no sourceIndex adjustment for conversion, only for callback output */
1378 errorInputLength=0;
1379
1380 /*
1381 * loop for offsets and error handling
1382 *
1383 * iterates at most 3 times:
1384 * 1. to clean up after the conversion function
1385 * 2. after the callback
1386 * 3. after the callback again if there was truncated input
1387 */
1388 for(;;) {
1389 /* update offsets if we write any */
1390 if(offsets!=NULL__null) {
1391 int32_t length=(int32_t)(pArgs->target-t);
1392 if(length>0) {
1393 _updateOffsets(offsets, length, sourceIndex, errorInputLength);
1394
1395 /*
1396 * if a converter handles offsets and updates the offsets
1397 * pointer at the end, then pArgs->offset should not change
1398 * here;
1399 * however, some converters do not handle offsets at all
1400 * (sourceIndex<0) or may not update the offsets pointer
1401 */
1402 pArgs->offsets=offsets+=length;
1403 }
1404
1405 if(sourceIndex>=0) {
1406 sourceIndex+=(int32_t)(pArgs->source-s);
1407 }
1408 }
1409
1410 if(cnv->preToULength<0) {
1411 /*
1412 * switch the source to new replay units (cannot occur while replaying)
1413 * after offset handling and before end-of-input and callback handling
1414 */
1415 if(realSource==NULL__null) {
1416 realSource=pArgs->source;
1417 realSourceLimit=pArgs->sourceLimit;
1418 realFlush=pArgs->flush;
1419 realSourceIndex=sourceIndex;
1420
1421 uprv_memcpy(replay, cnv->preToU, -cnv->preToULength)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(replay, cnv
->preToU, -cnv->preToULength); } while (false)
;
1422 pArgs->source=replay;
1423 pArgs->sourceLimit=replay-cnv->preToULength;
1424 pArgs->flush=FALSE0;
1425 if((sourceIndex+=cnv->preToULength)<0) {
1426 sourceIndex=-1;
1427 }
1428
1429 cnv->preToULength=0;
1430 } else {
1431 /* see implementation note before _fromUnicodeWithCallback() */
1432 U_ASSERT(realSource==NULL)(void)0;
1433 *err=U_INTERNAL_PROGRAM_ERROR;
1434 }
1435 }
1436
1437 /* update pointers */
1438 s=pArgs->source;
1439 t=pArgs->target;
1440
1441 if(U_SUCCESS(*err)) {
1442 if(s<pArgs->sourceLimit) {
1443 /*
1444 * continue with the conversion loop while there is still input left
1445 * (continue converting by breaking out of only the inner loop)
1446 */
1447 break;
1448 } else if(realSource!=NULL__null) {
1449 /* switch back from replaying to the real source and continue */
1450 pArgs->source=realSource;
1451 pArgs->sourceLimit=realSourceLimit;
1452 pArgs->flush=realFlush;
1453 sourceIndex=realSourceIndex;
1454
1455 realSource=NULL__null;
1456 break;
1457 } else if(pArgs->flush && cnv->toULength>0) {
1458 /*
1459 * the entire input stream is consumed
1460 * and there is a partial, truncated input sequence left
1461 */
1462
1463 /* inject an error and continue with callback handling */
1464 *err=U_TRUNCATED_CHAR_FOUND;
1465 calledCallback=FALSE0; /* new error condition */
1466 } else {
1467 /* input consumed */
1468 if(pArgs->flush) {
1469 /*
1470 * return to the conversion loop once more if the flush
1471 * flag is set and the conversion function has not
1472 * successfully processed the end of the input yet
1473 *
1474 * (continue converting by breaking out of only the inner loop)
1475 */
1476 if(!converterSawEndOfInput) {
1477 break;
1478 }
1479
1480 /* reset the converter without calling the callback function */
1481 _reset(cnv, UCNV_RESET_TO_UNICODE, FALSE0);
1482 }
1483
1484 /* done successfully */
1485 return;
1486 }
1487 }
1488
1489 /* U_FAILURE(*err) */
1490 {
1491 UErrorCode e;
1492
1493 if( calledCallback ||
1494 (e=*err)==U_BUFFER_OVERFLOW_ERROR ||
1495 (e!=U_INVALID_CHAR_FOUND &&
1496 e!=U_ILLEGAL_CHAR_FOUND &&
1497 e!=U_TRUNCATED_CHAR_FOUND &&
1498 e!=U_ILLEGAL_ESCAPE_SEQUENCE &&
1499 e!=U_UNSUPPORTED_ESCAPE_SEQUENCE)
1500 ) {
1501 /*
1502 * the callback did not or cannot resolve the error:
1503 * set output pointers and return
1504 *
1505 * the check for buffer overflow is redundant but it is
1506 * a high-runner case and hopefully documents the intent
1507 * well
1508 *
1509 * if we were replaying, then the replay buffer must be
1510 * copied back into the UConverter
1511 * and the real arguments must be restored
1512 */
1513 if(realSource!=NULL__null) {
1514 int32_t length;
1515
1516 U_ASSERT(cnv->preToULength==0)(void)0;
1517
1518 length=(int32_t)(pArgs->sourceLimit-pArgs->source);
1519 if(length>0) {
1520 uprv_memcpy(cnv->preToU, pArgs->source, length)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(cnv->preToU
, pArgs->source, length); } while (false)
;
1521 cnv->preToULength=(int8_t)-length;
1522 }
1523
1524 pArgs->source=realSource;
1525 pArgs->sourceLimit=realSourceLimit;
1526 pArgs->flush=realFlush;
1527 }
1528
1529 return;
1530 }
1531 }
1532
1533 /* copy toUBytes[] to invalidCharBuffer[] */
1534 errorInputLength=cnv->invalidCharLength=cnv->toULength;
1535 if(errorInputLength>0) {
1536 uprv_memcpy(cnv->invalidCharBuffer, cnv->toUBytes, errorInputLength)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(cnv->invalidCharBuffer
, cnv->toUBytes, errorInputLength); } while (false)
;
1537 }
1538
1539 /* set the converter state to deal with the next character */
1540 cnv->toULength=0;
1541
1542 /* call the callback function */
1543 if(cnv->toUCallbackReason==UCNV_ILLEGAL && *err==U_INVALID_CHAR_FOUND) {
1544 cnv->toUCallbackReason = UCNV_UNASSIGNED;
1545 }
1546 cnv->fromCharErrorBehaviour(cnv->toUContext, pArgs,
1547 cnv->invalidCharBuffer, errorInputLength,
1548 cnv->toUCallbackReason,
1549 err);
1550 cnv->toUCallbackReason = UCNV_ILLEGAL; /* reset to default value */
1551
1552 /*
1553 * loop back to the offset handling
1554 *
1555 * this flag will indicate after offset handling
1556 * that a callback was called;
1557 * if the callback did not resolve the error, then we return
1558 */
1559 calledCallback=TRUE1;
1560 }
1561 }
1562}
1563
1564/*
1565 * Output the toUnicode overflow buffer.
1566 * Call this function if(cnv->UCharErrorBufferLength>0).
1567 * @return TRUE if overflow
1568 */
1569static UBool
1570ucnv_outputOverflowToUnicode(UConverter *cnv,
1571 UChar **target, const UChar *targetLimit,
1572 int32_t **pOffsets,
1573 UErrorCode *err) {
1574 int32_t *offsets;
1575 UChar *overflow, *t;
1576 int32_t i, length;
1577
1578 t=*target;
1579 if(pOffsets!=NULL__null) {
1580 offsets=*pOffsets;
1581 } else {
1582 offsets=NULL__null;
1583 }
1584
1585 overflow=cnv->UCharErrorBuffer;
1586 length=cnv->UCharErrorBufferLength;
1587 i=0;
1588 while(i<length) {
1589 if(t==targetLimit) {
1590 /* the overflow buffer contains too much, keep the rest */
1591 int32_t j=0;
1592
1593 do {
1594 overflow[j++]=overflow[i++];
1595 } while(i<length);
1596
1597 cnv->UCharErrorBufferLength=(int8_t)j;
1598 *target=t;
1599 if(offsets!=NULL__null) {
1600 *pOffsets=offsets;
1601 }
1602 *err=U_BUFFER_OVERFLOW_ERROR;
1603 return TRUE1;
1604 }
1605
1606 /* copy the overflow contents to the target */
1607 *t++=overflow[i++];
1608 if(offsets!=NULL__null) {
1609 *offsets++=-1; /* no source index available for old output */
1610 }
1611 }
1612
1613 /* the overflow buffer is completely copied to the target */
1614 cnv->UCharErrorBufferLength=0;
1615 *target=t;
1616 if(offsets!=NULL__null) {
1617 *pOffsets=offsets;
1618 }
1619 return FALSE0;
1620}
1621
1622U_CAPIextern "C" void U_EXPORT2
1623ucnv_toUnicodeucnv_toUnicode_71(UConverter *cnv,
1624 UChar **target, const UChar *targetLimit,
1625 const char **source, const char *sourceLimit,
1626 int32_t *offsets,
1627 UBool flush,
1628 UErrorCode *err) {
1629 UConverterToUnicodeArgs args;
1630 const char *s;
1631 UChar *t;
1632
1633 /* check parameters */
1634 if(err==NULL__null || U_FAILURE(*err)) {
1635 return;
1636 }
1637
1638 if(cnv==NULL__null || target==NULL__null || source==NULL__null) {
1639 *err=U_ILLEGAL_ARGUMENT_ERROR;
1640 return;
1641 }
1642
1643 s=*source;
1644 t=*target;
1645
1646 if ((const void *)U_MAX_PTR(targetLimit)((void *)(((uintptr_t)(targetLimit)+0x7fffffffu) > (uintptr_t
)(targetLimit) ? ((uintptr_t)(targetLimit)+0x7fffffffu) : (uintptr_t
)-1))
== (const void *)targetLimit) {
1647 /*
1648 Prevent code from going into an infinite loop in case we do hit this
1649 limit. The limit pointer is expected to be on a UChar * boundary.
1650 This also prevents the next argument check from failing.
1651 */
1652 targetLimit = (const UChar *)(((const char *)targetLimit) - 1);
1653 }
1654
1655 /*
1656 * All these conditions should never happen.
1657 *
1658 * 1) Make sure that the limits are >= to the address source or target
1659 *
1660 * 2) Make sure that the buffer sizes do not exceed the number range for
1661 * int32_t because some functions use the size (in units or bytes)
1662 * rather than comparing pointers, and because offsets are int32_t values.
1663 *
1664 * size_t is guaranteed to be unsigned and large enough for the job.
1665 *
1666 * Return with an error instead of adjusting the limits because we would
1667 * not be able to maintain the semantics that either the source must be
1668 * consumed or the target filled (unless an error occurs).
1669 * An adjustment would be sourceLimit=t+0x7fffffff; for example.
1670 *
1671 * 3) Make sure that the user didn't incorrectly cast a UChar * pointer
1672 * to a char * pointer and provide an incomplete UChar code unit.
1673 */
1674 if (sourceLimit<s || targetLimit<t ||
1675 ((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s) ||
1676 ((size_t)(targetLimit-t)>(size_t)0x3fffffff && targetLimit>t) ||
1677 (((const char *)targetLimit-(const char *)t) & 1) != 0
1678 ) {
1679 *err=U_ILLEGAL_ARGUMENT_ERROR;
1680 return;
1681 }
1682
1683 /* output the target overflow buffer */
1684 if( cnv->UCharErrorBufferLength>0 &&
1685 ucnv_outputOverflowToUnicode(cnv, target, targetLimit, &offsets, err)
1686 ) {
1687 /* U_BUFFER_OVERFLOW_ERROR */
1688 return;
1689 }
1690 /* *target may have moved, therefore stop using t */
1691
1692 if(!flush && s==sourceLimit && cnv->preToULength>=0) {
1693 /* the overflow buffer is emptied and there is no new input: we are done */
1694 return;
1695 }
1696
1697 /*
1698 * Do not simply return with a buffer overflow error if
1699 * !flush && t==targetLimit
1700 * because it is possible that the source will not generate any output.
1701 * For example, the skip callback may be called;
1702 * it does not output anything.
1703 */
1704
1705 /* prepare the converter arguments */
1706 args.converter=cnv;
1707 args.flush=flush;
1708 args.offsets=offsets;
1709 args.source=s;
1710 args.sourceLimit=sourceLimit;
1711 args.target=*target;
1712 args.targetLimit=targetLimit;
1713 args.size=sizeof(args);
1714
1715 _toUnicodeWithCallback(&args, err);
1716
1717 *source=args.source;
1718 *target=args.target;
1719}
1720
1721/* ucnv_to/fromUChars() ----------------------------------------------------- */
1722
1723U_CAPIextern "C" int32_t U_EXPORT2
1724ucnv_fromUCharsucnv_fromUChars_71(UConverter *cnv,
1725 char *dest, int32_t destCapacity,
1726 const UChar *src, int32_t srcLength,
1727 UErrorCode *pErrorCode) {
1728 const UChar *srcLimit;
1729 char *originalDest, *destLimit;
1730 int32_t destLength;
1731
1732 /* check arguments */
1733 if(pErrorCode==NULL__null || U_FAILURE(*pErrorCode)) {
1734 return 0;
1735 }
1736
1737 if( cnv==NULL__null ||
1738 destCapacity<0 || (destCapacity>0 && dest==NULL__null) ||
1739 srcLength<-1 || (srcLength!=0 && src==NULL__null)
1740 ) {
1741 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1742 return 0;
1743 }
1744
1745 /* initialize */
1746 ucnv_resetFromUnicodeucnv_resetFromUnicode_71(cnv);
1747 originalDest=dest;
1748 if(srcLength==-1) {
1749 srcLength=u_strlenu_strlen_71(src);
1750 }
1751 if(srcLength>0) {
1752 srcLimit=src+srcLength;
1753 destCapacity=pinCapacity(dest, destCapacity);
1754 destLimit=dest+destCapacity;
1755
1756 /* perform the conversion */
1757 ucnv_fromUnicodeucnv_fromUnicode_71(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE1, pErrorCode);
1758 destLength=(int32_t)(dest-originalDest);
1759
1760 /* if an overflow occurs, then get the preflighting length */
1761 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
1762 char buffer[1024];
1763
1764 destLimit=buffer+sizeof(buffer);
1765 do {
1766 dest=buffer;
1767 *pErrorCode=U_ZERO_ERROR;
1768 ucnv_fromUnicodeucnv_fromUnicode_71(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE1, pErrorCode);
1769 destLength+=(int32_t)(dest-buffer);
1770 } while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
1771 }
1772 } else {
1773 destLength=0;
1774 }
1775
1776 return u_terminateCharsu_terminateChars_71(originalDest, destCapacity, destLength, pErrorCode);
1777}
1778
1779U_CAPIextern "C" int32_t U_EXPORT2
1780ucnv_toUCharsucnv_toUChars_71(UConverter *cnv,
1781 UChar *dest, int32_t destCapacity,
1782 const char *src, int32_t srcLength,
1783 UErrorCode *pErrorCode) {
1784 const char *srcLimit;
1785 UChar *originalDest, *destLimit;
1786 int32_t destLength;
1787
1788 /* check arguments */
1789 if(pErrorCode==NULL__null || U_FAILURE(*pErrorCode)) {
1790 return 0;
1791 }
1792
1793 if( cnv==NULL__null ||
1794 destCapacity<0 || (destCapacity>0 && dest==NULL__null) ||
1795 srcLength<-1 || (srcLength!=0 && src==NULL__null))
1796 {
1797 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1798 return 0;
1799 }
1800
1801 /* initialize */
1802 ucnv_resetToUnicodeucnv_resetToUnicode_71(cnv);
1803 originalDest=dest;
1804 if(srcLength==-1) {
1805 srcLength=(int32_t)uprv_strlen(src):: strlen(src);
1806 }
1807 if(srcLength>0) {
1808 srcLimit=src+srcLength;
1809 destCapacity=pinCapacity(dest, destCapacity);
1810 destLimit=dest+destCapacity;
1811
1812 /* perform the conversion */
1813 ucnv_toUnicodeucnv_toUnicode_71(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE1, pErrorCode);
1814 destLength=(int32_t)(dest-originalDest);
1815
1816 /* if an overflow occurs, then get the preflighting length */
1817 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR)
1818 {
1819 UChar buffer[1024];
1820
1821 destLimit=buffer+UPRV_LENGTHOF(buffer)(int32_t)(sizeof(buffer)/sizeof((buffer)[0]));
1822 do {
1823 dest=buffer;
1824 *pErrorCode=U_ZERO_ERROR;
1825 ucnv_toUnicodeucnv_toUnicode_71(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE1, pErrorCode);
1826 destLength+=(int32_t)(dest-buffer);
1827 }
1828 while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
1829 }
1830 } else {
1831 destLength=0;
1832 }
1833
1834 return u_terminateUCharsu_terminateUChars_71(originalDest, destCapacity, destLength, pErrorCode);
1835}
1836
1837/* ucnv_getNextUChar() ------------------------------------------------------ */
1838
1839U_CAPIextern "C" UChar32 U_EXPORT2
1840ucnv_getNextUCharucnv_getNextUChar_71(UConverter *cnv,
1841 const char **source, const char *sourceLimit,
1842 UErrorCode *err) {
1843 UConverterToUnicodeArgs args;
1844 UChar buffer[U16_MAX_LENGTH2];
1845 const char *s;
1846 UChar32 c;
1847 int32_t i, length;
1848
1849 /* check parameters */
1850 if(err==NULL__null || U_FAILURE(*err)) {
1851 return 0xffff;
1852 }
1853
1854 if(cnv==NULL__null || source==NULL__null) {
1855 *err=U_ILLEGAL_ARGUMENT_ERROR;
1856 return 0xffff;
1857 }
1858
1859 s=*source;
1860 if(sourceLimit<s) {
1861 *err=U_ILLEGAL_ARGUMENT_ERROR;
1862 return 0xffff;
1863 }
1864
1865 /*
1866 * Make sure that the buffer sizes do not exceed the number range for
1867 * int32_t because some functions use the size (in units or bytes)
1868 * rather than comparing pointers, and because offsets are int32_t values.
1869 *
1870 * size_t is guaranteed to be unsigned and large enough for the job.
1871 *
1872 * Return with an error instead of adjusting the limits because we would
1873 * not be able to maintain the semantics that either the source must be
1874 * consumed or the target filled (unless an error occurs).
1875 * An adjustment would be sourceLimit=t+0x7fffffff; for example.
1876 */
1877 if(((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s)) {
1878 *err=U_ILLEGAL_ARGUMENT_ERROR;
1879 return 0xffff;
1880 }
1881
1882 c=U_SENTINEL(-1);
1883
1884 /* flush the target overflow buffer */
1885 if(cnv->UCharErrorBufferLength>0) {
1886 UChar *overflow;
1887
1888 overflow=cnv->UCharErrorBuffer;
1889 i=0;
1890 length=cnv->UCharErrorBufferLength;
1891 U16_NEXT(overflow, i, length, c)do { (c)=(overflow)[(i)++]; if((((c)&0xfffffc00)==0xd800)
) { uint16_t __c2; if((i)!=(length) && (((__c2=(overflow
)[(i)])&0xfffffc00)==0xdc00)) { ++(i); (c)=(((UChar32)((c
))<<10UL)+(UChar32)(__c2)-((0xd800<<10UL)+0xdc00-
0x10000)); } } } while (false)
;
1892
1893 /* move the remaining overflow contents up to the beginning */
1894 if((cnv->UCharErrorBufferLength=(int8_t)(length-i))>0) {
1895 uprv_memmove(cnv->UCharErrorBuffer, cnv->UCharErrorBuffer+i,do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memmove(cnv->
UCharErrorBuffer, cnv->UCharErrorBuffer+i, cnv->UCharErrorBufferLength
*2); } while (false)
1896 cnv->UCharErrorBufferLength*U_SIZEOF_UCHAR)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memmove(cnv->
UCharErrorBuffer, cnv->UCharErrorBuffer+i, cnv->UCharErrorBufferLength
*2); } while (false)
;
1897 }
1898
1899 if(!U16_IS_LEAD(c)(((c)&0xfffffc00)==0xd800) || i<length) {
1900 return c;
1901 }
1902 /*
1903 * Continue if the overflow buffer contained only a lead surrogate,
1904 * in case the converter outputs single surrogates from complete
1905 * input sequences.
1906 */
1907 }
1908
1909 /*
1910 * flush==TRUE is implied for ucnv_getNextUChar()
1911 *
1912 * do not simply return even if s==sourceLimit because the converter may
1913 * not have seen flush==TRUE before
1914 */
1915
1916 /* prepare the converter arguments */
1917 args.converter=cnv;
1918 args.flush=TRUE1;
1919 args.offsets=NULL__null;
1920 args.source=s;
1921 args.sourceLimit=sourceLimit;
1922 args.target=buffer;
1923 args.targetLimit=buffer+1;
1924 args.size=sizeof(args);
1925
1926 if(c<0) {
1927 /*
1928 * call the native getNextUChar() implementation if we are
1929 * at a character boundary (toULength==0)
1930 *
1931 * unlike with _toUnicode(), getNextUChar() implementations must set
1932 * U_TRUNCATED_CHAR_FOUND for truncated input,
1933 * in addition to setting toULength/toUBytes[]
1934 */
1935 if(cnv->toULength==0 && cnv->sharedData->impl->getNextUChar!=NULL__null) {
1936 c=cnv->sharedData->impl->getNextUChar(&args, err);
1937 *source=s=args.source;
Although the value stored to 's' is used in the enclosing expression, the value is never actually read from 's'
1938 if(*err==U_INDEX_OUTOFBOUNDS_ERROR) {
1939 /* reset the converter without calling the callback function */
1940 _reset(cnv, UCNV_RESET_TO_UNICODE, FALSE0);
1941 return 0xffff; /* no output */
1942 } else if(U_SUCCESS(*err) && c>=0) {
1943 return c;
1944 /*
1945 * else fall through to use _toUnicode() because
1946 * UCNV_GET_NEXT_UCHAR_USE_TO_U: the native function did not want to handle it after all
1947 * U_FAILURE: call _toUnicode() for callback handling (do not output c)
1948 */
1949 }
1950 }
1951
1952 /* convert to one UChar in buffer[0], or handle getNextUChar() errors */
1953 _toUnicodeWithCallback(&args, err);
1954
1955 if(*err==U_BUFFER_OVERFLOW_ERROR) {
1956 *err=U_ZERO_ERROR;
1957 }
1958
1959 i=0;
1960 length=(int32_t)(args.target-buffer);
1961 } else {
1962 /* write the lead surrogate from the overflow buffer */
1963 buffer[0]=(UChar)c;
1964 args.target=buffer+1;
1965 i=0;
1966 length=1;
1967 }
1968
1969 /* buffer contents starts at i and ends before length */
1970
1971 if(U_FAILURE(*err)) {
1972 c=0xffff; /* no output */
1973 } else if(length==0) {
1974 /* no input or only state changes */
1975 *err=U_INDEX_OUTOFBOUNDS_ERROR;
1976 /* no need to reset explicitly because _toUnicodeWithCallback() did it */
1977 c=0xffff; /* no output */
1978 } else {
1979 c=buffer[0];
1980 i=1;
1981 if(!U16_IS_LEAD(c)(((c)&0xfffffc00)==0xd800)) {
1982 /* consume c=buffer[0], done */
1983 } else {
1984 /* got a lead surrogate, see if a trail surrogate follows */
1985 UChar c2;
1986
1987 if(cnv->UCharErrorBufferLength>0) {
1988 /* got overflow output from the conversion */
1989 if(U16_IS_TRAIL(c2=cnv->UCharErrorBuffer[0])(((c2=cnv->UCharErrorBuffer[0])&0xfffffc00)==0xdc00)) {
1990 /* got a trail surrogate, too */
1991 c=U16_GET_SUPPLEMENTARY(c, c2)(((UChar32)(c)<<10UL)+(UChar32)(c2)-((0xd800<<10UL
)+0xdc00-0x10000))
;
1992
1993 /* move the remaining overflow contents up to the beginning */
1994 if((--cnv->UCharErrorBufferLength)>0) {
1995 uprv_memmove(cnv->UCharErrorBuffer, cnv->UCharErrorBuffer+1,do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memmove(cnv->
UCharErrorBuffer, cnv->UCharErrorBuffer+1, cnv->UCharErrorBufferLength
*2); } while (false)
1996 cnv->UCharErrorBufferLength*U_SIZEOF_UCHAR)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memmove(cnv->
UCharErrorBuffer, cnv->UCharErrorBuffer+1, cnv->UCharErrorBufferLength
*2); } while (false)
;
1997 }
1998 } else {
1999 /* c is an unpaired lead surrogate, just return it */
2000 }
2001 } else if(args.source<sourceLimit) {
2002 /* convert once more, to buffer[1] */
2003 args.targetLimit=buffer+2;
2004 _toUnicodeWithCallback(&args, err);
2005 if(*err==U_BUFFER_OVERFLOW_ERROR) {
2006 *err=U_ZERO_ERROR;
2007 }
2008
2009 length=(int32_t)(args.target-buffer);
2010 if(U_SUCCESS(*err) && length==2 && U16_IS_TRAIL(c2=buffer[1])(((c2=buffer[1])&0xfffffc00)==0xdc00)) {
2011 /* got a trail surrogate, too */
2012 c=U16_GET_SUPPLEMENTARY(c, c2)(((UChar32)(c)<<10UL)+(UChar32)(c2)-((0xd800<<10UL
)+0xdc00-0x10000))
;
2013 i=2;
2014 }
2015 }
2016 }
2017 }
2018
2019 /*
2020 * move leftover output from buffer[i..length[
2021 * into the beginning of the overflow buffer
2022 */
2023 if(i<length) {
2024 /* move further overflow back */
2025 int32_t delta=length-i;
2026 if((length=cnv->UCharErrorBufferLength)>0) {
2027 uprv_memmove(cnv->UCharErrorBuffer+delta, cnv->UCharErrorBuffer,do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memmove(cnv->
UCharErrorBuffer+delta, cnv->UCharErrorBuffer, length*2); }
while (false)
2028 length*U_SIZEOF_UCHAR)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memmove(cnv->
UCharErrorBuffer+delta, cnv->UCharErrorBuffer, length*2); }
while (false)
;
2029 }
2030 cnv->UCharErrorBufferLength=(int8_t)(length+delta);
2031
2032 cnv->UCharErrorBuffer[0]=buffer[i++];
2033 if(delta>1) {
2034 cnv->UCharErrorBuffer[1]=buffer[i];
2035 }
2036 }
2037
2038 *source=args.source;
2039 return c;
2040}
2041
2042/* ucnv_convert() and siblings ---------------------------------------------- */
2043
2044U_CAPIextern "C" void U_EXPORT2
2045ucnv_convertExucnv_convertEx_71(UConverter *targetCnv, UConverter *sourceCnv,
2046 char **target, const char *targetLimit,
2047 const char **source, const char *sourceLimit,
2048 UChar *pivotStart, UChar **pivotSource,
2049 UChar **pivotTarget, const UChar *pivotLimit,
2050 UBool reset, UBool flush,
2051 UErrorCode *pErrorCode) {
2052 UChar pivotBuffer[CHUNK_SIZE1024];
2053 const UChar *myPivotSource;
2054 UChar *myPivotTarget;
2055 const char *s;
2056 char *t;
2057
2058 UConverterToUnicodeArgs toUArgs;
2059 UConverterFromUnicodeArgs fromUArgs;
2060 UConverterConvert convert;
2061
2062 /* error checking */
2063 if(pErrorCode==NULL__null || U_FAILURE(*pErrorCode)) {
2064 return;
2065 }
2066
2067 if( targetCnv==NULL__null || sourceCnv==NULL__null ||
2068 source==NULL__null || *source==NULL__null ||
2069 target==NULL__null || *target==NULL__null || targetLimit==NULL__null
2070 ) {
2071 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2072 return;
2073 }
2074
2075 s=*source;
2076 t=*target;
2077 if((sourceLimit!=NULL__null && sourceLimit<s) || targetLimit<t) {
2078 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2079 return;
2080 }
2081
2082 /*
2083 * Make sure that the buffer sizes do not exceed the number range for
2084 * int32_t. See ucnv_toUnicode() for a more detailed comment.
2085 */
2086 if(
2087 (sourceLimit!=NULL__null && ((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s)) ||
2088 ((size_t)(targetLimit-t)>(size_t)0x7fffffff && targetLimit>t)
2089 ) {
2090 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2091 return;
2092 }
2093
2094 if(pivotStart==NULL__null) {
2095 if(!flush) {
2096 /* streaming conversion requires an explicit pivot buffer */
2097 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2098 return;
2099 }
2100
2101 /* use the stack pivot buffer */
2102 myPivotSource=myPivotTarget=pivotStart=pivotBuffer;
2103 pivotSource=(UChar **)&myPivotSource;
2104 pivotTarget=&myPivotTarget;
2105 pivotLimit=pivotBuffer+CHUNK_SIZE1024;
2106 } else if( pivotStart>=pivotLimit ||
2107 pivotSource==NULL__null || *pivotSource==NULL__null ||
2108 pivotTarget==NULL__null || *pivotTarget==NULL__null ||
2109 pivotLimit==NULL__null
2110 ) {
2111 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2112 return;
2113 }
2114
2115 if(sourceLimit==NULL__null) {
2116 /* get limit of single-byte-NUL-terminated source string */
2117 sourceLimit=uprv_strchr(*source, 0):: strchr(*source, 0);
2118 }
2119
2120 if(reset) {
2121 ucnv_resetToUnicodeucnv_resetToUnicode_71(sourceCnv);
2122 ucnv_resetFromUnicodeucnv_resetFromUnicode_71(targetCnv);
2123 *pivotSource=*pivotTarget=pivotStart;
2124 } else if(targetCnv->charErrorBufferLength>0) {
2125 /* output the targetCnv overflow buffer */
2126 if(ucnv_outputOverflowFromUnicode(targetCnv, target, targetLimit, NULL__null, pErrorCode)) {
2127 /* U_BUFFER_OVERFLOW_ERROR */
2128 return;
2129 }
2130 /* *target has moved, therefore stop using t */
2131
2132 if( !flush &&
2133 targetCnv->preFromULength>=0 && *pivotSource==*pivotTarget &&
2134 sourceCnv->UCharErrorBufferLength==0 && sourceCnv->preToULength>=0 && s==sourceLimit
2135 ) {
2136 /* the fromUnicode overflow buffer is emptied and there is no new input: we are done */
2137 return;
2138 }
2139 }
2140
2141 /* Is direct-UTF-8 conversion available? */
2142 if( sourceCnv->sharedData->staticData->conversionType==UCNV_UTF8 &&
2143 targetCnv->sharedData->impl->fromUTF8!=NULL__null
2144 ) {
2145 convert=targetCnv->sharedData->impl->fromUTF8;
2146 } else if( targetCnv->sharedData->staticData->conversionType==UCNV_UTF8 &&
2147 sourceCnv->sharedData->impl->toUTF8!=NULL__null
2148 ) {
2149 convert=sourceCnv->sharedData->impl->toUTF8;
2150 } else {
2151 convert=NULL__null;
2152 }
2153
2154 /*
2155 * If direct-UTF-8 conversion is available, then we use a smaller
2156 * pivot buffer for error handling and partial matches
2157 * so that we quickly return to direct conversion.
2158 *
2159 * 32 is large enough for UCNV_EXT_MAX_UCHARS and UCNV_ERROR_BUFFER_LENGTH.
2160 *
2161 * We could reduce the pivot buffer size further, at the cost of
2162 * buffer overflows from callbacks.
2163 * The pivot buffer should not be smaller than the maximum number of
2164 * fromUnicode extension table input UChars
2165 * (for m:n conversion, see
2166 * targetCnv->sharedData->mbcs.extIndexes[UCNV_EXT_COUNT_UCHARS])
2167 * or 2 for surrogate pairs.
2168 *
2169 * Too small a buffer can cause thrashing between pivoting and direct
2170 * conversion, with function call overhead outweighing the benefits
2171 * of direct conversion.
2172 */
2173 if(convert!=NULL__null && (pivotLimit-pivotStart)>32) {
2174 pivotLimit=pivotStart+32;
2175 }
2176
2177 /* prepare the converter arguments */
2178 fromUArgs.converter=targetCnv;
2179 fromUArgs.flush=FALSE0;
2180 fromUArgs.offsets=NULL__null;
2181 fromUArgs.target=*target;
2182 fromUArgs.targetLimit=targetLimit;
2183 fromUArgs.size=sizeof(fromUArgs);
2184
2185 toUArgs.converter=sourceCnv;
2186 toUArgs.flush=flush;
2187 toUArgs.offsets=NULL__null;
2188 toUArgs.source=s;
2189 toUArgs.sourceLimit=sourceLimit;
2190 toUArgs.targetLimit=pivotLimit;
2191 toUArgs.size=sizeof(toUArgs);
2192
2193 /*
2194 * TODO: Consider separating this function into two functions,
2195 * extracting exactly the conversion loop,
2196 * for readability and to reduce the set of visible variables.
2197 *
2198 * Otherwise stop using s and t from here on.
2199 */
2200 s=t=NULL__null;
2201
2202 /*
2203 * conversion loop
2204 *
2205 * The sequence of steps in the loop may appear backward,
2206 * but the principle is simple:
2207 * In the chain of
2208 * source - sourceCnv overflow - pivot - targetCnv overflow - target
2209 * empty out later buffers before refilling them from earlier ones.
2210 *
2211 * The targetCnv overflow buffer is flushed out only once before the loop.
2212 */
2213 for(;;) {
2214 /*
2215 * if(pivot not empty or error or replay or flush fromUnicode) {
2216 * fromUnicode(pivot -> target);
2217 * }
2218 *
2219 * For pivoting conversion; and for direct conversion for
2220 * error callback handling and flushing the replay buffer.
2221 */
2222 if( *pivotSource<*pivotTarget ||
2223 U_FAILURE(*pErrorCode) ||
2224 targetCnv->preFromULength<0 ||
2225 fromUArgs.flush
2226 ) {
2227 fromUArgs.source=*pivotSource;
2228 fromUArgs.sourceLimit=*pivotTarget;
2229 _fromUnicodeWithCallback(&fromUArgs, pErrorCode);
2230 if(U_FAILURE(*pErrorCode)) {
2231 /* target overflow, or conversion error */
2232 *pivotSource=(UChar *)fromUArgs.source;
2233 break;
2234 }
2235
2236 /*
2237 * _fromUnicodeWithCallback() must have consumed the pivot contents
2238 * (*pivotSource==*pivotTarget) since it returned with U_SUCCESS()
2239 */
2240 }
2241
2242 /* The pivot buffer is empty; reset it so we start at pivotStart. */
2243 *pivotSource=*pivotTarget=pivotStart;
2244
2245 /*
2246 * if(sourceCnv overflow buffer not empty) {
2247 * move(sourceCnv overflow buffer -> pivot);
2248 * continue;
2249 * }
2250 */
2251 /* output the sourceCnv overflow buffer */
2252 if(sourceCnv->UCharErrorBufferLength>0) {
2253 if(ucnv_outputOverflowToUnicode(sourceCnv, pivotTarget, pivotLimit, NULL__null, pErrorCode)) {
2254 /* U_BUFFER_OVERFLOW_ERROR */
2255 *pErrorCode=U_ZERO_ERROR;
2256 }
2257 continue;
2258 }
2259
2260 /*
2261 * check for end of input and break if done
2262 *
2263 * Checking both flush and fromUArgs.flush ensures that the converters
2264 * have been called with the flush flag set if the ucnv_convertEx()
2265 * caller set it.
2266 */
2267 if( toUArgs.source==sourceLimit &&
2268 sourceCnv->preToULength>=0 && sourceCnv->toULength==0 &&
2269 (!flush || fromUArgs.flush)
2270 ) {
2271 /* done successfully */
2272 break;
2273 }
2274
2275 /*
2276 * use direct conversion if available
2277 * but not if continuing a partial match
2278 * or flushing the toUnicode replay buffer
2279 */
2280 if(convert!=NULL__null && targetCnv->preFromUFirstCP<0 && sourceCnv->preToULength==0) {
2281 if(*pErrorCode==U_USING_DEFAULT_WARNING) {
2282 /* remove a warning that may be set by this function */
2283 *pErrorCode=U_ZERO_ERROR;
2284 }
2285 convert(&fromUArgs, &toUArgs, pErrorCode);
2286 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
2287 break;
2288 } else if(U_FAILURE(*pErrorCode)) {
2289 if(sourceCnv->toULength>0) {
2290 /*
2291 * Fall through to calling _toUnicodeWithCallback()
2292 * for callback handling.
2293 *
2294 * The pivot buffer will be reset with
2295 * *pivotSource=*pivotTarget=pivotStart;
2296 * which indicates a toUnicode error to the caller
2297 * (*pivotSource==pivotStart shows no pivot UChars consumed).
2298 */
2299 } else {
2300 /*
2301 * Indicate a fromUnicode error to the caller
2302 * (*pivotSource>pivotStart shows some pivot UChars consumed).
2303 */
2304 *pivotSource=*pivotTarget=pivotStart+1;
2305 /*
2306 * Loop around to calling _fromUnicodeWithCallbacks()
2307 * for callback handling.
2308 */
2309 continue;
2310 }
2311 } else if(*pErrorCode==U_USING_DEFAULT_WARNING) {
2312 /*
2313 * No error, but the implementation requested to temporarily
2314 * fall back to pivoting.
2315 */
2316 *pErrorCode=U_ZERO_ERROR;
2317 /*
2318 * The following else branches are almost identical to the end-of-input
2319 * handling in _toUnicodeWithCallback().
2320 * Avoid calling it just for the end of input.
2321 */
2322 } else if(flush && sourceCnv->toULength>0) { /* flush==toUArgs.flush */
2323 /*
2324 * the entire input stream is consumed
2325 * and there is a partial, truncated input sequence left
2326 */
2327
2328 /* inject an error and continue with callback handling */
2329 *pErrorCode=U_TRUNCATED_CHAR_FOUND;
2330 } else {
2331 /* input consumed */
2332 if(flush) {
2333 /* reset the converters without calling the callback functions */
2334 _reset(sourceCnv, UCNV_RESET_TO_UNICODE, FALSE0);
2335 _reset(targetCnv, UCNV_RESET_FROM_UNICODE, FALSE0);
2336 }
2337
2338 /* done successfully */
2339 break;
2340 }
2341 }
2342
2343 /*
2344 * toUnicode(source -> pivot);
2345 *
2346 * For pivoting conversion; and for direct conversion for
2347 * error callback handling, continuing partial matches
2348 * and flushing the replay buffer.
2349 *
2350 * The pivot buffer is empty and reset.
2351 */
2352 toUArgs.target=pivotStart; /* ==*pivotTarget */
2353 /* toUArgs.targetLimit=pivotLimit; already set before the loop */
2354 _toUnicodeWithCallback(&toUArgs, pErrorCode);
2355 *pivotTarget=toUArgs.target;
2356 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
2357 /* pivot overflow: continue with the conversion loop */
2358 *pErrorCode=U_ZERO_ERROR;
2359 } else if(U_FAILURE(*pErrorCode) || (!flush && *pivotTarget==pivotStart)) {
2360 /* conversion error, or there was nothing left to convert */
2361 break;
2362 }
2363 /*
2364 * else:
2365 * _toUnicodeWithCallback() wrote into the pivot buffer,
2366 * continue with fromUnicode conversion.
2367 *
2368 * Set the fromUnicode flush flag if we flush and if toUnicode has
2369 * processed the end of the input.
2370 */
2371 if( flush && toUArgs.source==sourceLimit &&
2372 sourceCnv->preToULength>=0 &&
2373 sourceCnv->UCharErrorBufferLength==0
2374 ) {
2375 fromUArgs.flush=TRUE1;
2376 }
2377 }
2378
2379 /*
2380 * The conversion loop is exited when one of the following is true:
2381 * - the entire source text has been converted successfully to the target buffer
2382 * - a target buffer overflow occurred
2383 * - a conversion error occurred
2384 */
2385
2386 *source=toUArgs.source;
2387 *target=fromUArgs.target;
2388
2389 /* terminate the target buffer if possible */
2390 if(flush && U_SUCCESS(*pErrorCode)) {
2391 if(*target!=targetLimit) {
2392 **target=0;
2393 if(*pErrorCode==U_STRING_NOT_TERMINATED_WARNING) {
2394 *pErrorCode=U_ZERO_ERROR;
2395 }
2396 } else {
2397 *pErrorCode=U_STRING_NOT_TERMINATED_WARNING;
2398 }
2399 }
2400}
2401
2402/* internal implementation of ucnv_convert() etc. with preflighting */
2403static int32_t
2404ucnv_internalConvert(UConverter *outConverter, UConverter *inConverter,
2405 char *target, int32_t targetCapacity,
2406 const char *source, int32_t sourceLength,
2407 UErrorCode *pErrorCode) {
2408 UChar pivotBuffer[CHUNK_SIZE1024];
2409 UChar *pivot, *pivot2;
2410
2411 char *myTarget;
2412 const char *sourceLimit;
2413 const char *targetLimit;
2414 int32_t targetLength=0;
2415
2416 /* set up */
2417 if(sourceLength<0) {
2418 sourceLimit=uprv_strchr(source, 0):: strchr(source, 0);
2419 } else {
2420 sourceLimit=source+sourceLength;
2421 }
2422
2423 /* if there is no input data, we're done */
2424 if(source==sourceLimit) {
2425 return u_terminateCharsu_terminateChars_71(target, targetCapacity, 0, pErrorCode);
2426 }
2427
2428 pivot=pivot2=pivotBuffer;
2429 myTarget=target;
2430 targetLength=0;
2431
2432 if(targetCapacity>0) {
2433 /* perform real conversion */
2434 targetLimit=target+targetCapacity;
2435 ucnv_convertExucnv_convertEx_71(outConverter, inConverter,
2436 &myTarget, targetLimit,
2437 &source, sourceLimit,
2438 pivotBuffer, &pivot, &pivot2, pivotBuffer+CHUNK_SIZE1024,
2439 FALSE0,
2440 TRUE1,
2441 pErrorCode);
2442 targetLength=(int32_t)(myTarget-target);
2443 }
2444
2445 /*
2446 * If the output buffer is exhausted (or we are only "preflighting"), we need to stop writing
2447 * to it but continue the conversion in order to store in targetCapacity
2448 * the number of bytes that was required.
2449 */
2450 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR || targetCapacity==0)
2451 {
2452 char targetBuffer[CHUNK_SIZE1024];
2453
2454 targetLimit=targetBuffer+CHUNK_SIZE1024;
2455 do {
2456 *pErrorCode=U_ZERO_ERROR;
2457 myTarget=targetBuffer;
2458 ucnv_convertExucnv_convertEx_71(outConverter, inConverter,
2459 &myTarget, targetLimit,
2460 &source, sourceLimit,
2461 pivotBuffer, &pivot, &pivot2, pivotBuffer+CHUNK_SIZE1024,
2462 FALSE0,
2463 TRUE1,
2464 pErrorCode);
2465 targetLength+=(int32_t)(myTarget-targetBuffer);
2466 } while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
2467
2468 /* done with preflighting, set warnings and errors as appropriate */
2469 return u_terminateCharsu_terminateChars_71(target, targetCapacity, targetLength, pErrorCode);
2470 }
2471
2472 /* no need to call u_terminateChars() because ucnv_convertEx() took care of that */
2473 return targetLength;
2474}
2475
2476U_CAPIextern "C" int32_t U_EXPORT2
2477ucnv_convertucnv_convert_71(const char *toConverterName, const char *fromConverterName,
2478 char *target, int32_t targetCapacity,
2479 const char *source, int32_t sourceLength,
2480 UErrorCode *pErrorCode) {
2481 UConverter in, out; /* stack-allocated */
2482 UConverter *inConverter, *outConverter;
2483 int32_t targetLength;
2484
2485 if(pErrorCode==NULL__null || U_FAILURE(*pErrorCode)) {
2486 return 0;
2487 }
2488
2489 if( source==NULL__null || sourceLength<-1 ||
2490 targetCapacity<0 || (targetCapacity>0 && target==NULL__null)
2491 ) {
2492 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2493 return 0;
2494 }
2495
2496 /* if there is no input data, we're done */
2497 if(sourceLength==0 || (sourceLength<0 && *source==0)) {
2498 return u_terminateCharsu_terminateChars_71(target, targetCapacity, 0, pErrorCode);
2499 }
2500
2501 /* create the converters */
2502 inConverter=ucnv_createConverterucnv_createConverter_71(&in, fromConverterName, pErrorCode);
2503 if(U_FAILURE(*pErrorCode)) {
2504 return 0;
2505 }
2506
2507 outConverter=ucnv_createConverterucnv_createConverter_71(&out, toConverterName, pErrorCode);
2508 if(U_FAILURE(*pErrorCode)) {
2509 ucnv_closeucnv_close_71(inConverter);
2510 return 0;
2511 }
2512
2513 targetLength=ucnv_internalConvert(outConverter, inConverter,
2514 target, targetCapacity,
2515 source, sourceLength,
2516 pErrorCode);
2517
2518 ucnv_closeucnv_close_71(inConverter);
2519 ucnv_closeucnv_close_71(outConverter);
2520
2521 return targetLength;
2522}
2523
2524/* @internal */
2525static int32_t
2526ucnv_convertAlgorithmic(UBool convertToAlgorithmic,
2527 UConverterType algorithmicType,
2528 UConverter *cnv,
2529 char *target, int32_t targetCapacity,
2530 const char *source, int32_t sourceLength,
2531 UErrorCode *pErrorCode) {
2532 UConverter algoConverterStatic; /* stack-allocated */
2533 UConverter *algoConverter, *to, *from;
2534 int32_t targetLength;
2535
2536 if(pErrorCode==NULL__null || U_FAILURE(*pErrorCode)) {
2537 return 0;
2538 }
2539
2540 if( cnv==NULL__null || source==NULL__null || sourceLength<-1 ||
2541 targetCapacity<0 || (targetCapacity>0 && target==NULL__null)
2542 ) {
2543 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2544 return 0;
2545 }
2546
2547 /* if there is no input data, we're done */
2548 if(sourceLength==0 || (sourceLength<0 && *source==0)) {
2549 return u_terminateCharsu_terminateChars_71(target, targetCapacity, 0, pErrorCode);
2550 }
2551
2552 /* create the algorithmic converter */
2553 algoConverter=ucnv_createAlgorithmicConverterucnv_createAlgorithmicConverter_71(&algoConverterStatic, algorithmicType,
2554 "", 0, pErrorCode);
2555 if(U_FAILURE(*pErrorCode)) {
2556 return 0;
2557 }
2558
2559 /* reset the other converter */
2560 if(convertToAlgorithmic) {
2561 /* cnv->Unicode->algo */
2562 ucnv_resetToUnicodeucnv_resetToUnicode_71(cnv);
2563 to=algoConverter;
2564 from=cnv;
2565 } else {
2566 /* algo->Unicode->cnv */
2567 ucnv_resetFromUnicodeucnv_resetFromUnicode_71(cnv);
2568 from=algoConverter;
2569 to=cnv;
2570 }
2571
2572 targetLength=ucnv_internalConvert(to, from,
2573 target, targetCapacity,
2574 source, sourceLength,
2575 pErrorCode);
2576
2577 ucnv_closeucnv_close_71(algoConverter);
2578
2579 return targetLength;
2580}
2581
2582U_CAPIextern "C" int32_t U_EXPORT2
2583ucnv_toAlgorithmicucnv_toAlgorithmic_71(UConverterType algorithmicType,
2584 UConverter *cnv,
2585 char *target, int32_t targetCapacity,
2586 const char *source, int32_t sourceLength,
2587 UErrorCode *pErrorCode) {
2588 return ucnv_convertAlgorithmic(TRUE1, algorithmicType, cnv,
2589 target, targetCapacity,
2590 source, sourceLength,
2591 pErrorCode);
2592}
2593
2594U_CAPIextern "C" int32_t U_EXPORT2
2595ucnv_fromAlgorithmicucnv_fromAlgorithmic_71(UConverter *cnv,
2596 UConverterType algorithmicType,
2597 char *target, int32_t targetCapacity,
2598 const char *source, int32_t sourceLength,
2599 UErrorCode *pErrorCode) {
2600 return ucnv_convertAlgorithmic(FALSE0, algorithmicType, cnv,
2601 target, targetCapacity,
2602 source, sourceLength,
2603 pErrorCode);
2604}
2605
2606U_CAPIextern "C" UConverterType U_EXPORT2
2607ucnv_getTypeucnv_getType_71(const UConverter* converter)
2608{
2609 int8_t type = converter->sharedData->staticData->conversionType;
2610#if !UCONFIG_NO_LEGACY_CONVERSION0
2611 if(type == UCNV_MBCS) {
2612 return ucnv_MBCSGetTypeucnv_MBCSGetType_71(converter);
2613 }
2614#endif
2615 return (UConverterType)type;
2616}
2617
2618U_CAPIextern "C" void U_EXPORT2
2619ucnv_getStartersucnv_getStarters_71(const UConverter* converter,
2620 UBool starters[256],
2621 UErrorCode* err)
2622{
2623 if (err == NULL__null || U_FAILURE(*err)) {
2624 return;
2625 }
2626
2627 if(converter->sharedData->impl->getStarters != NULL__null) {
2628 converter->sharedData->impl->getStarters(converter, starters, err);
2629 } else {
2630 *err = U_ILLEGAL_ARGUMENT_ERROR;
2631 }
2632}
2633
2634static const UAmbiguousConverter *ucnv_getAmbiguous(const UConverter *cnv)
2635{
2636 UErrorCode errorCode;
2637 const char *name;
2638 int32_t i;
2639
2640 if(cnv==NULL__null) {
2641 return NULL__null;
2642 }
2643
2644 errorCode=U_ZERO_ERROR;
2645 name=ucnv_getNameucnv_getName_71(cnv, &errorCode);
2646 if(U_FAILURE(errorCode)) {
2647 return NULL__null;
2648 }
2649
2650 for(i=0; i<UPRV_LENGTHOF(ambiguousConverters)(int32_t)(sizeof(ambiguousConverters)/sizeof((ambiguousConverters
)[0]))
; ++i)
2651 {
2652 if(0==uprv_strcmp(name, ambiguousConverters[i].name):: strcmp(name, ambiguousConverters[i].name))
2653 {
2654 return ambiguousConverters+i;
2655 }
2656 }
2657
2658 return NULL__null;
2659}
2660
2661U_CAPIextern "C" void U_EXPORT2
2662ucnv_fixFileSeparatorucnv_fixFileSeparator_71(const UConverter *cnv,
2663 UChar* source,
2664 int32_t sourceLength) {
2665 const UAmbiguousConverter *a;
2666 int32_t i;
2667 UChar variant5c;
2668
2669 if(cnv==NULL__null || source==NULL__null || sourceLength<=0 || (a=ucnv_getAmbiguous(cnv))==NULL__null)
2670 {
2671 return;
2672 }
2673
2674 variant5c=a->variant5c;
2675 for(i=0; i<sourceLength; ++i) {
2676 if(source[i]==variant5c) {
2677 source[i]=0x5c;
2678 }
2679 }
2680}
2681
2682U_CAPIextern "C" UBool U_EXPORT2
2683ucnv_isAmbiguousucnv_isAmbiguous_71(const UConverter *cnv) {
2684 return (UBool)(ucnv_getAmbiguous(cnv)!=NULL__null);
2685}
2686
2687U_CAPIextern "C" void U_EXPORT2
2688ucnv_setFallbackucnv_setFallback_71(UConverter *cnv, UBool usesFallback)
2689{
2690 cnv->useFallback = usesFallback;
2691}
2692
2693U_CAPIextern "C" UBool U_EXPORT2
2694ucnv_usesFallbackucnv_usesFallback_71(const UConverter *cnv)
2695{
2696 return cnv->useFallback;
2697}
2698
2699U_CAPIextern "C" void U_EXPORT2
2700ucnv_getInvalidCharsucnv_getInvalidChars_71 (const UConverter * converter,
2701 char *errBytes,
2702 int8_t * len,
2703 UErrorCode * err)
2704{
2705 if (err == NULL__null || U_FAILURE(*err))
2706 {
2707 return;
2708 }
2709 if (len == NULL__null || errBytes == NULL__null || converter == NULL__null)
2710 {
2711 *err = U_ILLEGAL_ARGUMENT_ERROR;
2712 return;
2713 }
2714 if (*len < converter->invalidCharLength)
2715 {
2716 *err = U_INDEX_OUTOFBOUNDS_ERROR;
2717 return;
2718 }
2719 if ((*len = converter->invalidCharLength) > 0)
2720 {
2721 uprv_memcpy (errBytes, converter->invalidCharBuffer, *len)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(errBytes,
converter->invalidCharBuffer, *len); } while (false)
;
2722 }
2723}
2724
2725U_CAPIextern "C" void U_EXPORT2
2726ucnv_getInvalidUCharsucnv_getInvalidUChars_71 (const UConverter * converter,
2727 UChar *errChars,
2728 int8_t * len,
2729 UErrorCode * err)
2730{
2731 if (err == NULL__null || U_FAILURE(*err))
2732 {
2733 return;
2734 }
2735 if (len == NULL__null || errChars == NULL__null || converter == NULL__null)
2736 {
2737 *err = U_ILLEGAL_ARGUMENT_ERROR;
2738 return;
2739 }
2740 if (*len < converter->invalidUCharLength)
2741 {
2742 *err = U_INDEX_OUTOFBOUNDS_ERROR;
2743 return;
2744 }
2745 if ((*len = converter->invalidUCharLength) > 0)
2746 {
2747 u_memcpyu_memcpy_71 (errChars, converter->invalidUCharBuffer, *len);
2748 }
2749}
2750
2751#define SIG_MAX_LEN5 5
2752
2753U_CAPIextern "C" const char* U_EXPORT2
2754ucnv_detectUnicodeSignatureucnv_detectUnicodeSignature_71( const char* source,
2755 int32_t sourceLength,
2756 int32_t* signatureLength,
2757 UErrorCode* pErrorCode) {
2758 int32_t dummy;
2759
2760 /* initial 0xa5 bytes: make sure that if we read <SIG_MAX_LEN
2761 * bytes we don't misdetect something
2762 */
2763 char start[SIG_MAX_LEN5]={ '\xa5', '\xa5', '\xa5', '\xa5', '\xa5' };
2764 int i = 0;
2765
2766 if((pErrorCode==NULL__null) || U_FAILURE(*pErrorCode)){
2767 return NULL__null;
2768 }
2769
2770 if(source == NULL__null || sourceLength < -1){
2771 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
2772 return NULL__null;
2773 }
2774
2775 if(signatureLength == NULL__null) {
2776 signatureLength = &dummy;
2777 }
2778
2779 if(sourceLength==-1){
2780 sourceLength=(int32_t)uprv_strlen(source):: strlen(source);
2781 }
2782
2783
2784 while(i<sourceLength&& i<SIG_MAX_LEN5){
2785 start[i]=source[i];
2786 i++;
2787 }
2788
2789 if(start[0] == '\xFE' && start[1] == '\xFF') {
2790 *signatureLength=2;
2791 return "UTF-16BE";
2792 } else if(start[0] == '\xFF' && start[1] == '\xFE') {
2793 if(start[2] == '\x00' && start[3] =='\x00') {
2794 *signatureLength=4;
2795 return "UTF-32LE";
2796 } else {
2797 *signatureLength=2;
2798 return "UTF-16LE";
2799 }
2800 } else if(start[0] == '\xEF' && start[1] == '\xBB' && start[2] == '\xBF') {
2801 *signatureLength=3;
2802 return "UTF-8";
2803 } else if(start[0] == '\x00' && start[1] == '\x00' &&
2804 start[2] == '\xFE' && start[3]=='\xFF') {
2805 *signatureLength=4;
2806 return "UTF-32BE";
2807 } else if(start[0] == '\x0E' && start[1] == '\xFE' && start[2] == '\xFF') {
2808 *signatureLength=3;
2809 return "SCSU";
2810 } else if(start[0] == '\xFB' && start[1] == '\xEE' && start[2] == '\x28') {
2811 *signatureLength=3;
2812 return "BOCU-1";
2813 } else if(start[0] == '\x2B' && start[1] == '\x2F' && start[2] == '\x76') {
2814 /*
2815 * UTF-7: Initial U+FEFF is encoded as +/v8 or +/v9 or +/v+ or +/v/
2816 * depending on the second UTF-16 code unit.
2817 * Detect the entire, closed Unicode mode sequence +/v8- for only U+FEFF
2818 * if it occurs.
2819 *
2820 * So far we have +/v
2821 */
2822 if(start[3] == '\x38' && start[4] == '\x2D') {
2823 /* 5 bytes +/v8- */
2824 *signatureLength=5;
2825 return "UTF-7";
2826 } else if(start[3] == '\x38' || start[3] == '\x39' || start[3] == '\x2B' || start[3] == '\x2F') {
2827 /* 4 bytes +/v8 or +/v9 or +/v+ or +/v/ */
2828 *signatureLength=4;
2829 return "UTF-7";
2830 }
2831 }else if(start[0]=='\xDD' && start[1]== '\x73'&& start[2]=='\x66' && start[3]=='\x73'){
2832 *signatureLength=4;
2833 return "UTF-EBCDIC";
2834 }
2835
2836
2837 /* no known Unicode signature byte sequence recognized */
2838 *signatureLength=0;
2839 return NULL__null;
2840}
2841
2842U_CAPIextern "C" int32_t U_EXPORT2
2843ucnv_fromUCountPendingucnv_fromUCountPending_71(const UConverter* cnv, UErrorCode* status)
2844{
2845 if(status == NULL__null || U_FAILURE(*status)){
2846 return -1;
2847 }
2848 if(cnv == NULL__null){
2849 *status = U_ILLEGAL_ARGUMENT_ERROR;
2850 return -1;
2851 }
2852
2853 if(cnv->preFromUFirstCP >= 0){
2854 return U16_LENGTH(cnv->preFromUFirstCP)((uint32_t)(cnv->preFromUFirstCP)<=0xffff ? 1 : 2)+cnv->preFromULength ;
2855 }else if(cnv->preFromULength < 0){
2856 return -cnv->preFromULength ;
2857 }else if(cnv->fromUChar32 > 0){
2858 return 1;
2859 }
2860 return 0;
2861
2862}
2863
2864U_CAPIextern "C" int32_t U_EXPORT2
2865ucnv_toUCountPendingucnv_toUCountPending_71(const UConverter* cnv, UErrorCode* status){
2866
2867 if(status == NULL__null || U_FAILURE(*status)){
2868 return -1;
2869 }
2870 if(cnv == NULL__null){
2871 *status = U_ILLEGAL_ARGUMENT_ERROR;
2872 return -1;
2873 }
2874
2875 if(cnv->preToULength > 0){
2876 return cnv->preToULength ;
2877 }else if(cnv->preToULength < 0){
2878 return -cnv->preToULength;
2879 }else if(cnv->toULength > 0){
2880 return cnv->toULength;
2881 }
2882 return 0;
2883}
2884
2885U_CAPIextern "C" UBool U_EXPORT2
2886ucnv_isFixedWidthucnv_isFixedWidth_71(UConverter *cnv, UErrorCode *status){
2887 if (U_FAILURE(*status)) {
2888 return FALSE0;
2889 }
2890
2891 if (cnv == NULL__null) {
2892 *status = U_ILLEGAL_ARGUMENT_ERROR;
2893 return FALSE0;
2894 }
2895
2896 switch (ucnv_getTypeucnv_getType_71(cnv)) {
2897 case UCNV_SBCS:
2898 case UCNV_DBCS:
2899 case UCNV_UTF32_BigEndian:
2900 case UCNV_UTF32_LittleEndian:
2901 case UCNV_UTF32:
2902 case UCNV_US_ASCII:
2903 return TRUE1;
2904 default:
2905 return FALSE0;
2906 }
2907}
2908#endif
2909
2910/*
2911 * Hey, Emacs, please set the following:
2912 *
2913 * Local Variables:
2914 * indent-tabs-mode: nil
2915 * End:
2916 *
2917 */