Bug Summary

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