Bug Summary

File:out/../deps/icu-small/source/common/locdispnames.cpp
Warning:line 724, column 37
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name locdispnames.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D U_COMMON_IMPLEMENTATION=1 -D U_ATTRIBUTE_DEPRECATED= -D _CRT_SECURE_NO_DEPRECATE= -D U_STATIC_IMPLEMENTATION=1 -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/icu-small/source/common -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-deprecated-declarations -Wno-strict-aliasing -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/icu-small/source/common/locdispnames.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) 1997-2016, International Business Machines
7* Corporation and others. All Rights Reserved.
8*
9*******************************************************************************
10* file name: locdispnames.cpp
11* encoding: UTF-8
12* tab size: 8 (not used)
13* indentation:4
14*
15* created on: 2010feb25
16* created by: Markus W. Scherer
17*
18* Code for locale display names, separated out from other .cpp files
19* that then do not depend on resource bundle code and display name data.
20*/
21
22#include "unicode/utypes.h"
23#include "unicode/brkiter.h"
24#include "unicode/locid.h"
25#include "unicode/uenum.h"
26#include "unicode/uloc.h"
27#include "unicode/ures.h"
28#include "unicode/ustring.h"
29#include "bytesinkutil.h"
30#include "charstr.h"
31#include "cmemory.h"
32#include "cstring.h"
33#include "putilimp.h"
34#include "ulocimp.h"
35#include "uresimp.h"
36#include "ureslocs.h"
37#include "ustr_imp.h"
38
39// C++ API ----------------------------------------------------------------- ***
40
41U_NAMESPACE_BEGINnamespace icu_71 {
42
43UnicodeString&
44Locale::getDisplayLanguage(UnicodeString& dispLang) const
45{
46 return this->getDisplayLanguage(getDefault(), dispLang);
47}
48
49/*We cannot make any assumptions on the size of the output display strings
50* Yet, since we are calling through to a C API, we need to set limits on
51* buffer size. For all the following getDisplay functions we first attempt
52* to fill up a stack allocated buffer. If it is to small we heap allocated
53* the exact buffer we need copy it to the UnicodeString and delete it*/
54
55UnicodeString&
56Locale::getDisplayLanguage(const Locale &displayLocale,
57 UnicodeString &result) const {
58 UChar *buffer;
59 UErrorCode errorCode=U_ZERO_ERROR;
60 int32_t length;
61
62 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY157);
63 if(buffer==0) {
64 result.truncate(0);
65 return result;
66 }
67
68 length=uloc_getDisplayLanguageuloc_getDisplayLanguage_71(fullName, displayLocale.fullName,
69 buffer, result.getCapacity(),
70 &errorCode);
71 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
72
73 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
74 buffer=result.getBuffer(length);
75 if(buffer==0) {
76 result.truncate(0);
77 return result;
78 }
79 errorCode=U_ZERO_ERROR;
80 length=uloc_getDisplayLanguageuloc_getDisplayLanguage_71(fullName, displayLocale.fullName,
81 buffer, result.getCapacity(),
82 &errorCode);
83 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
84 }
85
86 return result;
87}
88
89UnicodeString&
90Locale::getDisplayScript(UnicodeString& dispScript) const
91{
92 return this->getDisplayScript(getDefault(), dispScript);
93}
94
95UnicodeString&
96Locale::getDisplayScript(const Locale &displayLocale,
97 UnicodeString &result) const {
98 UChar *buffer;
99 UErrorCode errorCode=U_ZERO_ERROR;
100 int32_t length;
101
102 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY157);
103 if(buffer==0) {
104 result.truncate(0);
105 return result;
106 }
107
108 length=uloc_getDisplayScriptuloc_getDisplayScript_71(fullName, displayLocale.fullName,
109 buffer, result.getCapacity(),
110 &errorCode);
111 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
112
113 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
114 buffer=result.getBuffer(length);
115 if(buffer==0) {
116 result.truncate(0);
117 return result;
118 }
119 errorCode=U_ZERO_ERROR;
120 length=uloc_getDisplayScriptuloc_getDisplayScript_71(fullName, displayLocale.fullName,
121 buffer, result.getCapacity(),
122 &errorCode);
123 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
124 }
125
126 return result;
127}
128
129UnicodeString&
130Locale::getDisplayCountry(UnicodeString& dispCntry) const
131{
132 return this->getDisplayCountry(getDefault(), dispCntry);
133}
134
135UnicodeString&
136Locale::getDisplayCountry(const Locale &displayLocale,
137 UnicodeString &result) const {
138 UChar *buffer;
139 UErrorCode errorCode=U_ZERO_ERROR;
140 int32_t length;
141
142 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY157);
143 if(buffer==0) {
144 result.truncate(0);
145 return result;
146 }
147
148 length=uloc_getDisplayCountryuloc_getDisplayCountry_71(fullName, displayLocale.fullName,
149 buffer, result.getCapacity(),
150 &errorCode);
151 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
152
153 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
154 buffer=result.getBuffer(length);
155 if(buffer==0) {
156 result.truncate(0);
157 return result;
158 }
159 errorCode=U_ZERO_ERROR;
160 length=uloc_getDisplayCountryuloc_getDisplayCountry_71(fullName, displayLocale.fullName,
161 buffer, result.getCapacity(),
162 &errorCode);
163 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
164 }
165
166 return result;
167}
168
169UnicodeString&
170Locale::getDisplayVariant(UnicodeString& dispVar) const
171{
172 return this->getDisplayVariant(getDefault(), dispVar);
173}
174
175UnicodeString&
176Locale::getDisplayVariant(const Locale &displayLocale,
177 UnicodeString &result) const {
178 UChar *buffer;
179 UErrorCode errorCode=U_ZERO_ERROR;
180 int32_t length;
181
182 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY157);
183 if(buffer==0) {
184 result.truncate(0);
185 return result;
186 }
187
188 length=uloc_getDisplayVariantuloc_getDisplayVariant_71(fullName, displayLocale.fullName,
189 buffer, result.getCapacity(),
190 &errorCode);
191 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
192
193 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
194 buffer=result.getBuffer(length);
195 if(buffer==0) {
196 result.truncate(0);
197 return result;
198 }
199 errorCode=U_ZERO_ERROR;
200 length=uloc_getDisplayVariantuloc_getDisplayVariant_71(fullName, displayLocale.fullName,
201 buffer, result.getCapacity(),
202 &errorCode);
203 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
204 }
205
206 return result;
207}
208
209UnicodeString&
210Locale::getDisplayName( UnicodeString& name ) const
211{
212 return this->getDisplayName(getDefault(), name);
213}
214
215UnicodeString&
216Locale::getDisplayName(const Locale &displayLocale,
217 UnicodeString &result) const {
218 UChar *buffer;
219 UErrorCode errorCode=U_ZERO_ERROR;
220 int32_t length;
221
222 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY157);
223 if(buffer==0) {
224 result.truncate(0);
225 return result;
226 }
227
228 length=uloc_getDisplayNameuloc_getDisplayName_71(fullName, displayLocale.fullName,
229 buffer, result.getCapacity(),
230 &errorCode);
231 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
232
233 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
234 buffer=result.getBuffer(length);
235 if(buffer==0) {
236 result.truncate(0);
237 return result;
238 }
239 errorCode=U_ZERO_ERROR;
240 length=uloc_getDisplayNameuloc_getDisplayName_71(fullName, displayLocale.fullName,
241 buffer, result.getCapacity(),
242 &errorCode);
243 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
244 }
245
246 return result;
247}
248
249#if ! UCONFIG_NO_BREAK_ITERATION0
250
251// -------------------------------------
252// Gets the objectLocale display name in the default locale language.
253UnicodeString& U_EXPORT2
254BreakIterator::getDisplayName(const Locale& objectLocale,
255 UnicodeString& name)
256{
257 return objectLocale.getDisplayName(name);
258}
259
260// -------------------------------------
261// Gets the objectLocale display name in the displayLocale language.
262UnicodeString& U_EXPORT2
263BreakIterator::getDisplayName(const Locale& objectLocale,
264 const Locale& displayLocale,
265 UnicodeString& name)
266{
267 return objectLocale.getDisplayName(displayLocale, name);
268}
269
270#endif
271
272
273U_NAMESPACE_END}
274
275// C API ------------------------------------------------------------------- ***
276
277U_NAMESPACE_USEusing namespace icu_71;
278
279/* ### Constants **************************************************/
280
281/* These strings describe the resources we attempt to load from
282 the locale ResourceBundle data file.*/
283static const char _kLanguages[] = "Languages";
284static const char _kScripts[] = "Scripts";
285static const char _kScriptsStandAlone[] = "Scripts%stand-alone";
286static const char _kCountries[] = "Countries";
287static const char _kVariants[] = "Variants";
288static const char _kKeys[] = "Keys";
289static const char _kTypes[] = "Types";
290//static const char _kRootName[] = "root";
291static const char _kCurrency[] = "currency";
292static const char _kCurrencies[] = "Currencies";
293static const char _kLocaleDisplayPattern[] = "localeDisplayPattern";
294static const char _kPattern[] = "pattern";
295static const char _kSeparator[] = "separator";
296
297/* ### Display name **************************************************/
298
299static int32_t
300_getStringOrCopyKey(const char *path, const char *locale,
301 const char *tableKey,
302 const char* subTableKey,
303 const char *itemKey,
304 const char *substitute,
305 UChar *dest, int32_t destCapacity,
306 UErrorCode *pErrorCode) {
307 const UChar *s = NULL__null;
308 int32_t length = 0;
309
310 if(itemKey==NULL__null) {
311 /* top-level item: normal resource bundle access */
312 icu::LocalUResourceBundlePointer rb(ures_openures_open_71(path, locale, pErrorCode));
313
314 if(U_SUCCESS(*pErrorCode)) {
315 s=ures_getStringByKeyures_getStringByKey_71(rb.getAlias(), tableKey, &length, pErrorCode);
316 /* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */
317 }
318 } else {
319 bool isLanguageCode = (uprv_strncmp(tableKey, _kLanguages, 9):: strncmp(tableKey, _kLanguages, 9) == 0);
320 /* Language code should not be a number. If it is, set the error code. */
321 if (isLanguageCode && uprv_strtol(itemKey, NULL, 10):: strtol(itemKey, __null, 10)) {
322 *pErrorCode = U_MISSING_RESOURCE_ERROR;
323 } else {
324 /* second-level item, use special fallback */
325 s=uloc_getTableStringWithFallbackuloc_getTableStringWithFallback_71(path, locale,
326 tableKey,
327 subTableKey,
328 itemKey,
329 &length,
330 pErrorCode);
331 if (U_FAILURE(*pErrorCode) && isLanguageCode && itemKey != nullptr) {
332 // convert itemKey locale code to canonical form and try again, ICU-20870
333 *pErrorCode = U_ZERO_ERROR;
334 Locale canonKey = Locale::createCanonical(itemKey);
335 s=uloc_getTableStringWithFallbackuloc_getTableStringWithFallback_71(path, locale,
336 tableKey,
337 subTableKey,
338 canonKey.getName(),
339 &length,
340 pErrorCode);
341 }
342 }
343 }
344
345 if(U_SUCCESS(*pErrorCode)) {
346 int32_t copyLength=uprv_minuprv_min_71(length, destCapacity);
347 if(copyLength>0 && s != NULL__null) {
348 u_memcpyu_memcpy_71(dest, s, copyLength);
349 }
350 } else {
351 /* no string from a resource bundle: convert the substitute */
352 length=(int32_t)uprv_strlen(substitute):: strlen(substitute);
353 u_charsToUCharsu_charsToUChars_71(substitute, dest, uprv_minuprv_min_71(length, destCapacity));
354 *pErrorCode=U_USING_DEFAULT_WARNING;
355 }
356
357 return u_terminateUCharsu_terminateUChars_71(dest, destCapacity, length, pErrorCode);
358}
359
360typedef int32_t U_CALLCONV UDisplayNameGetter(const char *, char *, int32_t, UErrorCode *);
361
362static int32_t
363_getDisplayNameForComponent(const char *locale,
364 const char *displayLocale,
365 UChar *dest, int32_t destCapacity,
366 UDisplayNameGetter *getter,
367 const char *tag,
368 UErrorCode *pErrorCode) {
369 char localeBuffer[ULOC_FULLNAME_CAPACITY157*4];
370 int32_t length;
371 UErrorCode localStatus;
372 const char* root = NULL__null;
373
374 /* argument checking */
375 if(pErrorCode==NULL__null || U_FAILURE(*pErrorCode)) {
376 return 0;
377 }
378
379 if(destCapacity<0 || (destCapacity>0 && dest==NULL__null)) {
380 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
381 return 0;
382 }
383
384 localStatus = U_ZERO_ERROR;
385 length=(*getter)(locale, localeBuffer, sizeof(localeBuffer), &localStatus);
386 if(U_FAILURE(localStatus) || localStatus==U_STRING_NOT_TERMINATED_WARNING) {
387 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
388 return 0;
389 }
390 if(length==0) {
391 // For the display name, we treat this as unknown language (ICU-20273).
392 if (getter == uloc_getLanguageuloc_getLanguage_71) {
393 uprv_strcpy(localeBuffer, "und"):: strcpy(localeBuffer, "und");
394 } else {
395 return u_terminateUCharsu_terminateUChars_71(dest, destCapacity, 0, pErrorCode);
396 }
397 }
398
399 root = tag == _kCountries ? U_ICUDATA_REGION"icudt" "71" "l" "-" "region" : U_ICUDATA_LANG"icudt" "71" "l" "-" "lang";
400
401 return _getStringOrCopyKey(root, displayLocale,
402 tag, NULL__null, localeBuffer,
403 localeBuffer,
404 dest, destCapacity,
405 pErrorCode);
406}
407
408U_CAPIextern "C" int32_t U_EXPORT2
409uloc_getDisplayLanguageuloc_getDisplayLanguage_71(const char *locale,
410 const char *displayLocale,
411 UChar *dest, int32_t destCapacity,
412 UErrorCode *pErrorCode) {
413 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
414 uloc_getLanguageuloc_getLanguage_71, _kLanguages, pErrorCode);
415}
416
417U_CAPIextern "C" int32_t U_EXPORT2
418uloc_getDisplayScriptuloc_getDisplayScript_71(const char* locale,
419 const char* displayLocale,
420 UChar *dest, int32_t destCapacity,
421 UErrorCode *pErrorCode)
422{
423 UErrorCode err = U_ZERO_ERROR;
424 int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
425 uloc_getScriptuloc_getScript_71, _kScriptsStandAlone, &err);
426
427 if (destCapacity == 0 && err == U_BUFFER_OVERFLOW_ERROR) {
428 // For preflight, return the max of the value and the fallback.
429 int32_t fallback_res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
430 uloc_getScriptuloc_getScript_71, _kScripts, pErrorCode);
431 return (fallback_res > res) ? fallback_res : res;
432 }
433 if ( err == U_USING_DEFAULT_WARNING ) {
434 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
435 uloc_getScriptuloc_getScript_71, _kScripts, pErrorCode);
436 } else {
437 *pErrorCode = err;
438 return res;
439 }
440}
441
442static int32_t
443uloc_getDisplayScriptInContext(const char* locale,
444 const char* displayLocale,
445 UChar *dest, int32_t destCapacity,
446 UErrorCode *pErrorCode)
447{
448 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
449 uloc_getScriptuloc_getScript_71, _kScripts, pErrorCode);
450}
451
452U_CAPIextern "C" int32_t U_EXPORT2
453uloc_getDisplayCountryuloc_getDisplayCountry_71(const char *locale,
454 const char *displayLocale,
455 UChar *dest, int32_t destCapacity,
456 UErrorCode *pErrorCode) {
457 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
458 uloc_getCountryuloc_getCountry_71, _kCountries, pErrorCode);
459}
460
461/*
462 * TODO separate variant1_variant2_variant3...
463 * by getting each tag's display string and concatenating them with ", "
464 * in between - similar to uloc_getDisplayName()
465 */
466U_CAPIextern "C" int32_t U_EXPORT2
467uloc_getDisplayVariantuloc_getDisplayVariant_71(const char *locale,
468 const char *displayLocale,
469 UChar *dest, int32_t destCapacity,
470 UErrorCode *pErrorCode) {
471 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
472 uloc_getVariantuloc_getVariant_71, _kVariants, pErrorCode);
473}
474
475/* Instead of having a separate pass for 'special' patterns, reintegrate the two
476 * so we don't get bitten by preflight bugs again. We can be reasonably efficient
477 * without two separate code paths, this code isn't that performance-critical.
478 *
479 * This code is general enough to deal with patterns that have a prefix or swap the
480 * language and remainder components, since we gave developers enough rope to do such
481 * things if they futz with the pattern data. But since we don't give them a way to
482 * specify a pattern for arbitrary combinations of components, there's not much use in
483 * that. I don't think our data includes such patterns, the only variable I know if is
484 * whether there is a space before the open paren, or not. Oh, and zh uses different
485 * chars than the standard open/close paren (which ja and ko use, btw).
486 */
487U_CAPIextern "C" int32_t U_EXPORT2
488uloc_getDisplayNameuloc_getDisplayName_71(const char *locale,
489 const char *displayLocale,
490 UChar *dest, int32_t destCapacity,
491 UErrorCode *pErrorCode)
492{
493 static const UChar defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */
494 static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */
495 static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */
496 static const int32_t subLen = 3;
497 static const UChar defaultPattern[10] = {
498 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000
499 }; /* {0} ({1}) */
500 static const int32_t defaultPatLen = 9;
501 static const int32_t defaultSub0Pos = 0;
502 static const int32_t defaultSub1Pos = 5;
503
504 int32_t length; /* of formatted result */
505
506 const UChar *separator;
507 int32_t sepLen = 0;
508 const UChar *pattern;
509 int32_t patLen = 0;
510 int32_t sub0Pos, sub1Pos;
511
512 UChar formatOpenParen = 0x0028; // (
513 UChar formatReplaceOpenParen = 0x005B; // [
514 UChar formatCloseParen = 0x0029; // )
515 UChar formatReplaceCloseParen = 0x005D; // ]
516
517 UBool haveLang = TRUE1; /* assume true, set false if we find we don't have
518 a lang component in the locale */
519 UBool haveRest = TRUE1; /* assume true, set false if we find we don't have
520 any other component in the locale */
521 UBool retry = FALSE0; /* set true if we need to retry, see below */
522
523 int32_t langi = 0; /* index of the language substitution (0 or 1), virtually always 0 */
524
525 if(pErrorCode==NULL__null || U_FAILURE(*pErrorCode)) {
1
Assuming 'pErrorCode' is not equal to NULL
526 return 0;
527 }
528
529 if(destCapacity<0 || (destCapacity>0 && dest==NULL__null)) {
2
Assuming 'destCapacity' is >= 0
3
Assuming 'destCapacity' is <= 0
530 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
531 return 0;
532 }
533
534 {
535 UErrorCode status = U_ZERO_ERROR;
536
537 icu::LocalUResourceBundlePointer locbundle(
538 ures_openures_open_71(U_ICUDATA_LANG"icudt" "71" "l" "-" "lang", displayLocale, &status));
539 icu::LocalUResourceBundlePointer dspbundle(
540 ures_getByKeyWithFallbackures_getByKeyWithFallback_71(locbundle.getAlias(), _kLocaleDisplayPattern, NULL__null, &status));
541
542 separator=ures_getStringByKeyWithFallbackures_getStringByKeyWithFallback_71(dspbundle.getAlias(), _kSeparator, &sepLen, &status);
543 pattern=ures_getStringByKeyWithFallbackures_getStringByKeyWithFallback_71(dspbundle.getAlias(), _kPattern, &patLen, &status);
544 }
545
546 /* If we couldn't find any data, then use the defaults */
547 if(sepLen == 0) {
4
Assuming 'sepLen' is not equal to 0
5
Taking false branch
548 separator = defaultSeparator;
549 }
550 /* #10244: Even though separator is now a pattern, it is awkward to handle it as such
551 * here since we are trying to build the display string in place in the dest buffer,
552 * and to handle it as a pattern would entail having separate storage for the
553 * substrings that need to be combined (the first of which may be the result of
554 * previous such combinations). So for now we continue to treat the portion between
555 * {0} and {1} as a string to be appended when joining substrings, ignoring anything
556 * that is before {0} or after {1} (no existing separator pattern has any such thing).
557 * This is similar to how pattern is handled below.
558 */
559 {
560 UChar *p0=u_strstru_strstr_71(separator, sub0);
561 UChar *p1=u_strstru_strstr_71(separator, sub1);
562 if (p0==NULL__null || p1==NULL__null || p1<p0) {
6
Assuming 'p0' is not equal to NULL
7
Assuming 'p1' is not equal to NULL
8
Assuming 'p1' is >= 'p0'
9
Taking false branch
563 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
564 return 0;
565 }
566 separator = (const UChar *)p0 + subLen;
567 sepLen = static_cast<int32_t>(p1 - separator);
568 }
569
570 if(patLen==0 || (patLen==defaultPatLen && !u_strncmpu_strncmp_71(pattern, defaultPattern, patLen))) {
10
Assuming 'patLen' is not equal to 0
11
Assuming 'patLen' is not equal to 'defaultPatLen'
571 pattern=defaultPattern;
572 patLen=defaultPatLen;
573 sub0Pos=defaultSub0Pos;
574 sub1Pos=defaultSub1Pos;
575 // use default formatOpenParen etc. set above
576 } else { /* non-default pattern */
577 UChar *p0=u_strstru_strstr_71(pattern, sub0);
578 UChar *p1=u_strstru_strstr_71(pattern, sub1);
579 if (p0==NULL__null || p1==NULL__null) {
12
Assuming 'p0' is not equal to NULL
13
Assuming 'p1' is not equal to NULL
14
Taking false branch
580 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
581 return 0;
582 }
583 sub0Pos = static_cast<int32_t>(p0-pattern);
584 sub1Pos = static_cast<int32_t>(p1-pattern);
585 if (sub1Pos < sub0Pos) { /* a very odd pattern */
15
Assuming 'sub1Pos' is >= 'sub0Pos'
16
Taking false branch
586 int32_t t=sub0Pos; sub0Pos=sub1Pos; sub1Pos=t;
587 langi=1;
588 }
589 if (u_strchru_strchr_71(pattern, 0xFF08) != NULL__null) {
17
Assuming the condition is false
18
Taking false branch
590 formatOpenParen = 0xFF08; // fullwidth (
591 formatReplaceOpenParen = 0xFF3B; // fullwidth [
592 formatCloseParen = 0xFF09; // fullwidth )
593 formatReplaceCloseParen = 0xFF3D; // fullwidth ]
594 }
595 }
596
597 /* We loop here because there is one case in which after the first pass we could need to
598 * reextract the data. If there's initial padding before the first element, we put in
599 * the padding and then write that element. If it turns out there's no second element,
600 * we didn't need the padding. If we do need the data (no preflight), and the first element
601 * would have fit but for the padding, we need to reextract. In this case (only) we
602 * adjust the parameters so padding is not added, and repeat.
603 */
604 do {
605 UChar* p=dest;
606 int32_t patPos=0; /* position in the pattern, used for non-substitution portions */
607 int32_t langLen=0; /* length of language substitution */
608 int32_t langPos=0; /* position in output of language substitution */
609 int32_t restLen=0; /* length of 'everything else' substitution */
610 int32_t restPos=0; /* position in output of 'everything else' substitution */
611 icu::LocalUEnumerationPointer kenum; /* keyword enumeration */
612
613 /* prefix of pattern, extremely likely to be empty */
614 if(sub0Pos) {
19
Assuming 'sub0Pos' is 0
20
Taking false branch
615 if(destCapacity >= sub0Pos) {
616 while (patPos < sub0Pos) {
617 *p++ = pattern[patPos++];
618 }
619 } else {
620 patPos=sub0Pos;
621 }
622 length=sub0Pos;
623 } else {
624 length=0;
625 }
626
627 for(int32_t subi=0,resti=0;subi<2;) { /* iterate through patterns 0 and 1*/
21
Loop condition is true. Entering loop body
32
Loop condition is true. Entering loop body
43
Loop condition is true. Entering loop body
628 UBool subdone = FALSE0; /* set true when ready to move to next substitution */
629
630 /* prep p and cap for calls to get display components, pin cap to 0 since
631 they complain if cap is negative */
632 int32_t cap=destCapacity-length;
633 if (cap
21.1
'cap' is <= 0
43.1
'cap' is > 0
<= 0
) {
22
Taking true branch
33
Assuming 'cap' is > 0
34
Taking false branch
44
Taking false branch
634 cap=0;
635 } else {
636 p=dest+length;
637 }
638
639 if (subi
22.1
'subi' is equal to 'langi'
34.1
'subi' is not equal to 'langi'
44.1
'subi' is not equal to 'langi'
== langi) { /* {0}*/
23
Taking true branch
35
Taking false branch
45
Taking false branch
640 if(haveLang
23.1
'haveLang' is 1
) {
24
Taking true branch
641 langPos=length;
642 langLen=uloc_getDisplayLanguageuloc_getDisplayLanguage_71(locale, displayLocale, p, cap, pErrorCode);
643 length+=langLen;
644 haveLang=langLen>0;
25
Assuming 'langLen' is > 0
645 }
646 subdone=TRUE1;
647 } else { /* {1} */
648 if(!haveRest
35.1
'haveRest' is 1
45.1
'haveRest' is 1
) {
36
Taking false branch
46
Taking false branch
649 subdone=TRUE1;
650 } else {
651 int32_t len; /* length of component (plus other stuff) we just fetched */
652 switch(resti++) {
37
Control jumps to 'case 0:' at line 653
47
Control jumps to 'case 1:' at line 657
653 case 0:
654 restPos=length;
655 len=uloc_getDisplayScriptInContext(locale, displayLocale, p, cap, pErrorCode);
656 break;
657 case 1:
658 len=uloc_getDisplayCountryuloc_getDisplayCountry_71(locale, displayLocale, p, cap, pErrorCode);
659 break;
660 case 2:
661 len=uloc_getDisplayVariantuloc_getDisplayVariant_71(locale, displayLocale, p, cap, pErrorCode);
662 break;
663 case 3:
664 kenum.adoptInstead(uloc_openKeywordsuloc_openKeywords_71(locale, pErrorCode));
665 U_FALLTHROUGH[[clang::fallthrough]];
666 default: {
667 const char* kw=uenum_nextuenum_next_71(kenum.getAlias(), &len, pErrorCode);
668 if (kw == NULL__null) {
669 len=0; /* mark that we didn't add a component */
670 subdone=TRUE1;
671 } else {
672 /* incorporating this behavior into the loop made it even more complex,
673 so just special case it here */
674 len = uloc_getDisplayKeyworduloc_getDisplayKeyword_71(kw, displayLocale, p, cap, pErrorCode);
675 if(len) {
676 if(len < cap) {
677 p[len]=0x3d; /* '=', assume we'll need it */
678 }
679 len+=1;
680
681 /* adjust for call to get keyword */
682 cap-=len;
683 if(cap <= 0) {
684 cap=0;
685 } else {
686 p+=len;
687 }
688 }
689 /* reset for call below */
690 if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) {
691 *pErrorCode=U_ZERO_ERROR;
692 }
693 int32_t vlen = uloc_getDisplayKeywordValueuloc_getDisplayKeywordValue_71(locale, kw, displayLocale,
694 p, cap, pErrorCode);
695 if(len) {
696 if(vlen==0) {
697 --len; /* remove unneeded '=' */
698 }
699 /* restore cap and p to what they were at start */
700 cap=destCapacity-length;
701 if(cap <= 0) {
702 cap=0;
703 } else {
704 p=dest+length;
705 }
706 }
707 len+=vlen; /* total we added for key + '=' + value */
708 }
709 } break;
710 } /* end switch */
711
712 if (len
38.1
'len' is <= 0
>0
) {
38
Execution continues on line 712
39
Taking false branch
48
Execution continues on line 712
49
Assuming 'len' is > 0
50
Taking true branch
713 /* we added a component, so add separator and write it if there's room. */
714 if(len+sepLen<=cap) {
51
Assuming the condition is true
52
Taking true branch
715 const UChar * plimit = p + len;
716 for (; p < plimit; p++) {
53
Loop condition is false. Execution continues on line 723
717 if (*p == formatOpenParen) {
718 *p = formatReplaceOpenParen;
719 } else if (*p == formatCloseParen) {
720 *p = formatReplaceCloseParen;
721 }
722 }
723 for(int32_t i=0;i<sepLen;++i) {
54
Assuming 'i' is < 'sepLen'
55
Loop condition is true. Entering loop body
724 *p++=separator[i];
56
Null pointer value stored to 'p'
57
Dereference of null pointer
725 }
726 }
727 length+=len+sepLen;
728 } else if(subdone
39.1
'subdone' is 0
) {
40
Taking false branch
729 /* remove separator if we added it */
730 if (length!=restPos) {
731 length-=sepLen;
732 }
733 restLen=length-restPos;
734 haveRest=restLen>0;
735 }
736 }
737 }
738
739 if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) {
26
Assuming the condition is false
27
Taking false branch
41
Taking false branch
740 *pErrorCode=U_ZERO_ERROR;
741 }
742
743 if(subdone
27.1
'subdone' is 1
41.1
'subdone' is 0
) {
42
Taking false branch
744 if(haveLang
27.2
'haveLang' is 1
&& haveRest
27.3
'haveRest' is 1
) {
28
Taking true branch
745 /* append internal portion of pattern, the first time,
746 or last portion of pattern the second time */
747 int32_t padLen;
748 patPos+=subLen;
749 padLen=(subi
28.1
'subi' is equal to 0
==0 ? sub1Pos : patLen)-patPos;
29
'?' condition is true
750 if(length+padLen <= destCapacity) {
30
Assuming the condition is false
31
Taking false branch
751 p=dest+length;
752 for(int32_t i=0;i<padLen;++i) {
753 *p++=pattern[patPos++];
754 }
755 } else {
756 patPos+=padLen;
757 }
758 length+=padLen;
759 } else if(subi==0) {
760 /* don't have first component, reset for second component */
761 sub0Pos=0;
762 length=0;
763 } else if(length>0) {
764 /* true length is the length of just the component we got. */
765 length=haveLang?langLen:restLen;
766 if(dest && sub0Pos!=0) {
767 if (sub0Pos+length<=destCapacity) {
768 /* first component not at start of result,
769 but we have full component in buffer. */
770 u_memmoveu_memmove_71(dest, dest+(haveLang?langPos:restPos), length);
771 } else {
772 /* would have fit, but didn't because of pattern prefix. */
773 sub0Pos=0; /* stops initial padding (and a second retry,
774 so we won't end up here again) */
775 retry=TRUE1;
776 }
777 }
778 }
779
780 ++subi; /* move on to next substitution */
781 }
782 }
783 } while(retry);
784
785 return u_terminateUCharsu_terminateUChars_71(dest, destCapacity, length, pErrorCode);
786}
787
788U_CAPIextern "C" int32_t U_EXPORT2
789uloc_getDisplayKeyworduloc_getDisplayKeyword_71(const char* keyword,
790 const char* displayLocale,
791 UChar* dest,
792 int32_t destCapacity,
793 UErrorCode* status){
794
795 /* argument checking */
796 if(status==NULL__null || U_FAILURE(*status)) {
797 return 0;
798 }
799
800 if(destCapacity<0 || (destCapacity>0 && dest==NULL__null)) {
801 *status=U_ILLEGAL_ARGUMENT_ERROR;
802 return 0;
803 }
804
805
806 /* pass itemKey=NULL to look for a top-level item */
807 return _getStringOrCopyKey(U_ICUDATA_LANG"icudt" "71" "l" "-" "lang", displayLocale,
808 _kKeys, NULL__null,
809 keyword,
810 keyword,
811 dest, destCapacity,
812 status);
813
814}
815
816
817#define UCURRENCY_DISPLAY_NAME_INDEX1 1
818
819U_CAPIextern "C" int32_t U_EXPORT2
820uloc_getDisplayKeywordValueuloc_getDisplayKeywordValue_71( const char* locale,
821 const char* keyword,
822 const char* displayLocale,
823 UChar* dest,
824 int32_t destCapacity,
825 UErrorCode* status){
826
827
828 /* argument checking */
829 if(status==NULL__null || U_FAILURE(*status)) {
830 return 0;
831 }
832
833 if(destCapacity<0 || (destCapacity>0 && dest==NULL__null)) {
834 *status=U_ILLEGAL_ARGUMENT_ERROR;
835 return 0;
836 }
837
838 /* get the keyword value */
839 CharString keywordValue;
840 {
841 CharStringByteSink sink(&keywordValue);
842 ulocimp_getKeywordValueulocimp_getKeywordValue_71(locale, keyword, sink, status);
843 }
844
845 /*
846 * if the keyword is equal to currency .. then to get the display name
847 * we need to do the fallback ourselves
848 */
849 if(uprv_stricmpuprv_stricmp_71(keyword, _kCurrency)==0){
850
851 int32_t dispNameLen = 0;
852 const UChar *dispName = NULL__null;
853
854 icu::LocalUResourceBundlePointer bundle(
855 ures_openures_open_71(U_ICUDATA_CURR"icudt" "71" "l" "-" "curr", displayLocale, status));
856 icu::LocalUResourceBundlePointer currencies(
857 ures_getByKeyures_getByKey_71(bundle.getAlias(), _kCurrencies, NULL__null, status));
858 icu::LocalUResourceBundlePointer currency(
859 ures_getByKeyWithFallbackures_getByKeyWithFallback_71(currencies.getAlias(), keywordValue.data(), NULL__null, status));
860
861 dispName = ures_getStringByIndexures_getStringByIndex_71(currency.getAlias(), UCURRENCY_DISPLAY_NAME_INDEX1, &dispNameLen, status);
862
863 if(U_FAILURE(*status)){
864 if(*status == U_MISSING_RESOURCE_ERROR){
865 /* we just want to write the value over if nothing is available */
866 *status = U_USING_DEFAULT_WARNING;
867 }else{
868 return 0;
869 }
870 }
871
872 /* now copy the dispName over if not NULL */
873 if(dispName != NULL__null){
874 if(dispNameLen <= destCapacity){
875 u_memcpyu_memcpy_71(dest, dispName, dispNameLen);
876 return u_terminateUCharsu_terminateUChars_71(dest, destCapacity, dispNameLen, status);
877 }else{
878 *status = U_BUFFER_OVERFLOW_ERROR;
879 return dispNameLen;
880 }
881 }else{
882 /* we have not found the display name for the value .. just copy over */
883 if(keywordValue.length() <= destCapacity){
884 u_charsToUCharsu_charsToUChars_71(keywordValue.data(), dest, keywordValue.length());
885 return u_terminateUCharsu_terminateUChars_71(dest, destCapacity, keywordValue.length(), status);
886 }else{
887 *status = U_BUFFER_OVERFLOW_ERROR;
888 return keywordValue.length();
889 }
890 }
891
892
893 }else{
894
895 return _getStringOrCopyKey(U_ICUDATA_LANG"icudt" "71" "l" "-" "lang", displayLocale,
896 _kTypes, keyword,
897 keywordValue.data(),
898 keywordValue.data(),
899 dest, destCapacity,
900 status);
901 }
902}