Bug Summary

File:root/firefox-clang/intl/icu/source/i18n/ucol_sit.cpp
Warning:line 362, column 25
Null pointer passed as 1st argument to string concatenation function

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 ucol_sit.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/i18n -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/icu/i18n -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_I18N_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/i18n -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/icu/i18n -I /root/firefox-clang/intl/icu/source/common -I /root/firefox-clang/mfbt/double-conversion -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/i18n/ucol_sit.cpp
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4*******************************************************************************
5* Copyright (C) 2004-2016, International Business Machines
6* Corporation and others. All Rights Reserved.
7*******************************************************************************
8* file name: ucol_sit.cpp
9* encoding: UTF-8
10* tab size: 8 (not used)
11* indentation:4
12*
13* Modification history
14* Date Name Comments
15* 03/12/2004 weiv Creation
16*/
17
18#include "unicode/ustring.h"
19#include "unicode/udata.h"
20#include "unicode/utf16.h"
21#include "utracimp.h"
22#include "ucol_imp.h"
23#include "ulocimp.h"
24#include "cmemory.h"
25#include "cstring.h"
26#include "uresimp.h"
27#include "unicode/coll.h"
28#include "unicode/stringpiece.h"
29#include "charstr.h"
30
31U_NAMESPACE_USEusing namespace icu_77;
32
33#ifdef UCOL_TRACE_SIT
34# include <stdio.h>
35#endif
36
37#if !UCONFIG_NO_COLLATION0
38
39#include "unicode/tblcoll.h"
40
41enum OptionsList {
42 UCOL_SIT_LANGUAGE = 0,
43 UCOL_SIT_SCRIPT = 1,
44 UCOL_SIT_REGION = 2,
45 UCOL_SIT_VARIANT = 3,
46 UCOL_SIT_KEYWORD = 4,
47 UCOL_SIT_PROVIDER = 5,
48 UCOL_SIT_LOCELEMENT_MAX = UCOL_SIT_PROVIDER, /* the last element that's part of LocElements */
49
50 UCOL_SIT_BCP47,
51 UCOL_SIT_STRENGTH,
52 UCOL_SIT_CASE_LEVEL,
53 UCOL_SIT_CASE_FIRST,
54 UCOL_SIT_NUMERIC_COLLATION,
55 UCOL_SIT_ALTERNATE_HANDLING,
56 UCOL_SIT_NORMALIZATION_MODE,
57 UCOL_SIT_FRENCH_COLLATION,
58 UCOL_SIT_HIRAGANA_QUATERNARY,
59 UCOL_SIT_VARIABLE_TOP,
60 UCOL_SIT_VARIABLE_TOP_VALUE,
61 UCOL_SIT_ITEMS_COUNT
62};
63
64/* option starters chars. */
65static const char alternateHArg = 'A';
66static const char variableTopValArg = 'B';
67static const char caseFirstArg = 'C';
68static const char numericCollArg = 'D';
69static const char caseLevelArg = 'E';
70static const char frenchCollArg = 'F';
71static const char hiraganaQArg = 'H';
72static const char keywordArg = 'K';
73static const char languageArg = 'L';
74static const char normArg = 'N';
75static const char providerArg = 'P';
76static const char regionArg = 'R';
77static const char strengthArg = 'S';
78static const char variableTopArg = 'T';
79static const char variantArg = 'V';
80static const char RFC3066Arg = 'X';
81static const char scriptArg = 'Z';
82
83static const char collationKeyword[] = "@collation=";
84static const char providerKeyword[] = "@sp=";
85
86
87static const int32_t locElementCount = UCOL_SIT_LOCELEMENT_MAX+1;
88static const int32_t locElementCapacity = 32;
89static const int32_t loc3066Capacity = 256;
90
91/* structure containing specification of a collator. Initialized
92 * from a short string. Also used to construct a short string from a
93 * collator instance
94 */
95struct CollatorSpec {
96 inline CollatorSpec();
97
98 CharString locElements[locElementCount];
99 CharString locale;
100 UColAttributeValue options[UCOL_ATTRIBUTE_COUNT];
101 uint32_t variableTopValue;
102 char16_t variableTopString[locElementCapacity];
103 int32_t variableTopStringLen;
104 UBool variableTopSet;
105 CharString entries[UCOL_SIT_ITEMS_COUNT];
106};
107
108CollatorSpec::CollatorSpec() :
109locale(),
110variableTopValue(0),
111variableTopString(),
112variableTopSet(false)
113 {
114 // set collation options to default
115 for(int32_t i = 0; i < UCOL_ATTRIBUTE_COUNT; i++) {
116 options[i] = UCOL_DEFAULT;
117 }
118}
119
120
121/* structure for converting between character attribute
122 * representation and real collation attribute value.
123 */
124struct AttributeConversion {
125 char letter;
126 UColAttributeValue value;
127};
128
129static const AttributeConversion conversions[12] = {
130 { '1', UCOL_PRIMARY },
131 { '2', UCOL_SECONDARY },
132 { '3', UCOL_TERTIARY },
133 { '4', UCOL_QUATERNARY },
134 { 'D', UCOL_DEFAULT },
135 { 'I', UCOL_IDENTICAL },
136 { 'L', UCOL_LOWER_FIRST },
137 { 'N', UCOL_NON_IGNORABLE },
138 { 'O', UCOL_ON },
139 { 'S', UCOL_SHIFTED },
140 { 'U', UCOL_UPPER_FIRST },
141 { 'X', UCOL_OFF }
142};
143
144
145static UColAttributeValue
146ucol_sit_letterToAttributeValue(char letter, UErrorCode *status) {
147 uint32_t i = 0;
148 for(i = 0; i < UPRV_LENGTHOF(conversions)(int32_t)(sizeof(conversions)/sizeof((conversions)[0])); i++) {
149 if(conversions[i].letter == letter) {
150 return conversions[i].value;
151 }
152 }
153 *status = U_ILLEGAL_ARGUMENT_ERROR;
154#ifdef UCOL_TRACE_SIT
155 fprintf(stderrstderr, "%s:%d: unknown letter %c: %s\n", __FILE__"/root/firefox-clang/intl/icu/source/i18n/ucol_sit.cpp", __LINE__155, letter, u_errorNameu_errorName_77(*status));
156#endif
157 return UCOL_DEFAULT;
158}
159
160/* function prototype for functions used to parse a short string */
161U_CDECL_BEGINextern "C" {
162typedef const char* U_CALLCONV
163ActionFunction(CollatorSpec *spec, uint32_t value1, const char* string,
164 UErrorCode *status);
165U_CDECL_END}
166
167U_CDECL_BEGINextern "C" {
168static const char* U_CALLCONV
169_processLocaleElement(CollatorSpec *spec, uint32_t value, const char* string,
170 UErrorCode *status)
171{
172 do {
173 if(value == UCOL_SIT_LANGUAGE || value == UCOL_SIT_KEYWORD || value == UCOL_SIT_PROVIDER) {
174 spec->locElements[value].append(uprv_toloweruprv_asciitolower_77(*string), *status);
175 } else {
176 spec->locElements[value].append(*string, *status);
177 }
178 } while(*(++string) != '_' && *string && U_SUCCESS(*status));
179 // don't skip the underscore at the end
180 return string;
181}
182U_CDECL_END}
183
184U_CDECL_BEGINextern "C" {
185static const char* U_CALLCONV
186_processRFC3066Locale(CollatorSpec *spec, uint32_t, const char* string,
187 UErrorCode *status)
188{
189 char terminator = *string;
190 string++;
191 const char *end = uprv_strchr(string+1, terminator):: strchr(string+1, terminator);
192 if(end == nullptr || end - string >= loc3066Capacity) {
193 *status = U_BUFFER_OVERFLOW_ERROR;
194 return string;
195 } else {
196 spec->locale.copyFrom(CharString(string, static_cast<int32_t>(end-string), *status), *status);
197 return end+1;
198 }
199}
200
201U_CDECL_END}
202
203U_CDECL_BEGINextern "C" {
204static const char* U_CALLCONV
205_processCollatorOption(CollatorSpec *spec, uint32_t option, const char* string,
206 UErrorCode *status)
207{
208 spec->options[option] = ucol_sit_letterToAttributeValue(*string, status);
209 if((*(++string) != '_' && *string) || U_FAILURE(*status)) {
210#ifdef UCOL_TRACE_SIT
211 fprintf(stderrstderr, "%s:%d: unknown collator option at '%s': %s\n", __FILE__"/root/firefox-clang/intl/icu/source/i18n/ucol_sit.cpp", __LINE__211, string, u_errorNameu_errorName_77(*status));
212#endif
213 *status = U_ILLEGAL_ARGUMENT_ERROR;
214 }
215 return string;
216}
217U_CDECL_END}
218
219
220static char16_t
221readHexCodeUnit(const char **string, UErrorCode *status)
222{
223 char16_t result = 0;
224 int32_t value = 0;
225 char c;
226 int32_t noDigits = 0;
227 while((c = **string) != 0 && noDigits < 4) {
228 if( c >= '0' && c <= '9') {
229 value = c - '0';
230 } else if ( c >= 'a' && c <= 'f') {
231 value = c - 'a' + 10;
232 } else if ( c >= 'A' && c <= 'F') {
233 value = c - 'A' + 10;
234 } else {
235 *status = U_ILLEGAL_ARGUMENT_ERROR;
236#ifdef UCOL_TRACE_SIT
237 fprintf(stderrstderr, "%s:%d: Bad hex char at '%s': %s\n", __FILE__"/root/firefox-clang/intl/icu/source/i18n/ucol_sit.cpp", __LINE__237, *string, u_errorNameu_errorName_77(*status));
238#endif
239 return 0;
240 }
241 result = (result << 4) | static_cast<char16_t>(value);
242 noDigits++;
243 (*string)++;
244 }
245 // if the string was terminated before we read 4 digits, set an error
246 if(noDigits < 4) {
247 *status = U_ILLEGAL_ARGUMENT_ERROR;
248#ifdef UCOL_TRACE_SIT
249 fprintf(stderrstderr, "%s:%d: Short (only %d digits, wanted 4) at '%s': %s\n", __FILE__"/root/firefox-clang/intl/icu/source/i18n/ucol_sit.cpp", __LINE__249, noDigits,*string, u_errorNameu_errorName_77(*status));
250#endif
251 }
252 return result;
253}
254
255U_CDECL_BEGINextern "C" {
256static const char* U_CALLCONV
257_processVariableTop(CollatorSpec *spec, uint32_t value1, const char* string, UErrorCode *status)
258{
259 // get four digits
260 int32_t i = 0;
261 if(!value1) {
262 while(U_SUCCESS(*status) && i < locElementCapacity && *string != 0 && *string != '_') {
263 spec->variableTopString[i++] = readHexCodeUnit(&string, status);
264 }
265 spec->variableTopStringLen = i;
266 if(i == locElementCapacity && *string != 0 && *string != '_') {
267 *status = U_BUFFER_OVERFLOW_ERROR;
268 }
269 } else {
270 spec->variableTopValue = readHexCodeUnit(&string, status);
271 }
272 if(U_SUCCESS(*status)) {
273 spec->variableTopSet = true;
274 }
275 return string;
276}
277U_CDECL_END}
278
279
280/* Table for parsing short strings */
281struct ShortStringOptions {
282 char optionStart;
283 ActionFunction *action;
284 uint32_t attr;
285};
286
287static const ShortStringOptions options[UCOL_SIT_ITEMS_COUNT] =
288{
289/* 10 ALTERNATE_HANDLING */ {alternateHArg, _processCollatorOption, UCOL_ALTERNATE_HANDLING }, // alternate N, S, D
290/* 15 VARIABLE_TOP_VALUE */ {variableTopValArg, _processVariableTop, 1 },
291/* 08 CASE_FIRST */ {caseFirstArg, _processCollatorOption, UCOL_CASE_FIRST }, // case first L, U, X, D
292/* 09 NUMERIC_COLLATION */ {numericCollArg, _processCollatorOption, UCOL_NUMERIC_COLLATION }, // codan O, X, D
293/* 07 CASE_LEVEL */ {caseLevelArg, _processCollatorOption, UCOL_CASE_LEVEL }, // case level O, X, D
294/* 12 FRENCH_COLLATION */ {frenchCollArg, _processCollatorOption, UCOL_FRENCH_COLLATION }, // french O, X, D
295/* 13 HIRAGANA_QUATERNARY] */ {hiraganaQArg, _processCollatorOption, UCOL_HIRAGANA_QUATERNARY_MODE }, // hiragana O, X, D
296/* 04 KEYWORD */ {keywordArg, _processLocaleElement, UCOL_SIT_KEYWORD }, // keyword
297/* 00 LANGUAGE */ {languageArg, _processLocaleElement, UCOL_SIT_LANGUAGE }, // language
298/* 11 NORMALIZATION_MODE */ {normArg, _processCollatorOption, UCOL_NORMALIZATION_MODE }, // norm O, X, D
299/* 02 REGION */ {regionArg, _processLocaleElement, UCOL_SIT_REGION }, // region
300/* 06 STRENGTH */ {strengthArg, _processCollatorOption, UCOL_STRENGTH }, // strength 1, 2, 3, 4, I, D
301/* 14 VARIABLE_TOP */ {variableTopArg, _processVariableTop, 0 },
302/* 03 VARIANT */ {variantArg, _processLocaleElement, UCOL_SIT_VARIANT }, // variant
303/* 05 RFC3066BIS */ {RFC3066Arg, _processRFC3066Locale, 0 }, // rfc3066bis locale name
304/* 01 SCRIPT */ {scriptArg, _processLocaleElement, UCOL_SIT_SCRIPT }, // script
305/* PROVIDER */ {providerArg, _processLocaleElement, UCOL_SIT_PROVIDER }
306};
307
308
309static
310const char* ucol_sit_readOption(const char *start, CollatorSpec *spec,
311 UErrorCode *status)
312{
313 int32_t i = 0;
314
315 for(i = 0; i < UCOL_SIT_ITEMS_COUNT; i++) {
316 if(*start == options[i].optionStart) {
317 const char* end = options[i].action(spec, options[i].attr, start+1, status);
318#ifdef UCOL_TRACE_SIT
319 fprintf(stderrstderr, "***Set %d to %s...\n", i, start);
320#endif
321 // assume 'start' does not go away through all this
322 spec->entries[i].copyFrom(CharString(start, static_cast<int32_t>(end - start), *status), *status);
323 return end;
324 }
325 }
326 *status = U_ILLEGAL_ARGUMENT_ERROR;
327#ifdef UCOL_TRACE_SIT
328 fprintf(stderrstderr, "%s:%d: Unknown option at '%s': %s\n", __FILE__"/root/firefox-clang/intl/icu/source/i18n/ucol_sit.cpp", __LINE__328, start, u_errorNameu_errorName_77(*status));
329#endif
330 return start;
331}
332
333static const char*
334ucol_sit_readSpecs(CollatorSpec *s, const char *string,
335 UParseError *parseError, UErrorCode *status)
336{
337 const char *definition = string;
338 while(U_SUCCESS(*status) && *string) {
339 string = ucol_sit_readOption(string, s, status);
340 // advance over '_'
341 while(*string && *string == '_') {
342 string++;
343 }
344 }
345 if(U_FAILURE(*status)) {
346 parseError->offset = static_cast<int32_t>(string - definition);
347 }
348 return string;
349}
350
351static
352int32_t ucol_sit_dumpSpecs(CollatorSpec *s, char *destination, int32_t capacity, UErrorCode *status)
353{
354 int32_t i = 0, j = 0;
355 int32_t len = 0;
356 char optName;
357 if(U_SUCCESS(*status)) {
8
Taking true branch
358 for(i = 0; i < UCOL_SIT_ITEMS_COUNT; i++) {
9
Loop condition is true. Entering loop body
17
Loop condition is true. Entering loop body
359 if(!s->entries[i].isEmpty()) {
10
Taking true branch
18
Taking true branch
360 if(len
10.1
'len' is 0
) {
11
Taking false branch
19
Assuming 'len' is not equal to 0
20
Taking true branch
361 if(len < capacity) {
21
Assuming 'len' is < 'capacity'
22
Taking true branch
362 uprv_strcat(destination, "_"):: strcat(destination, "_");
23
Null pointer passed as 1st argument to string concatenation function
363 }
364 len++;
365 }
366 optName = s->entries[i][0];
367 if(optName == languageArg || optName == regionArg || optName == variantArg || optName == keywordArg) {
12
Assuming 'optName' is not equal to 'languageArg'
13
Assuming 'optName' is not equal to 'regionArg'
14
Assuming 'optName' is not equal to 'variantArg'
15
Assuming 'optName' is not equal to 'keywordArg'
16
Taking false branch
368 for(j = 0; j < s->entries[i].length(); j++) {
369 if(len + j < capacity) {
370 destination[len+j] = uprv_toupperuprv_toupper_77(s->entries[i][j]);
371 }
372 }
373 len += s->entries[i].length();
374 } else {
375 len += s->entries[i].extract(destination + len, capacity - len, *status);
376 }
377 }
378 }
379 return len;
380 } else {
381 return 0;
382 }
383}
384
385static void
386ucol_sit_calculateWholeLocale(CollatorSpec *s, UErrorCode &status) {
387 // put the locale together, unless we have a done
388 // locale
389 if(s->locale.isEmpty()) {
390 // first the language
391 s->locale.append(s->locElements[UCOL_SIT_LANGUAGE], status);
392 // then the script, if present
393 if(!s->locElements[UCOL_SIT_SCRIPT].isEmpty()) {
394 s->locale.append("_", status);
395 s->locale.append(s->locElements[UCOL_SIT_SCRIPT], status);
396 }
397 // then the region, if present
398 if(!s->locElements[UCOL_SIT_REGION].isEmpty()) {
399 s->locale.append("_", status);
400 s->locale.append(s->locElements[UCOL_SIT_REGION], status);
401 } else if(!s->locElements[UCOL_SIT_VARIANT].isEmpty()) { // if there is a variant, we need an underscore
402 s->locale.append("_", status);
403 }
404 // add variant, if there
405 if(!s->locElements[UCOL_SIT_VARIANT].isEmpty()) {
406 s->locale.append("_", status);
407 s->locale.append(s->locElements[UCOL_SIT_VARIANT], status);
408 }
409
410 // if there is a collation keyword, add that too
411 if(!s->locElements[UCOL_SIT_KEYWORD].isEmpty()) {
412 s->locale.append(collationKeyword, status);
413 s->locale.append(s->locElements[UCOL_SIT_KEYWORD], status);
414 }
415
416 // if there is a provider keyword, add that too
417 if(!s->locElements[UCOL_SIT_PROVIDER].isEmpty()) {
418 s->locale.append(providerKeyword, status);
419 s->locale.append(s->locElements[UCOL_SIT_PROVIDER], status);
420 }
421 }
422}
423
424
425U_CAPIextern "C" void U_EXPORT2
426ucol_prepareShortStringOpenucol_prepareShortStringOpen_77( const char *definition,
427 UBool,
428 UParseError *parseError,
429 UErrorCode *status)
430{
431 if(U_FAILURE(*status)) return;
432
433 UParseError internalParseError;
434
435 if(!parseError) {
436 parseError = &internalParseError;
437 }
438 parseError->line = 0;
439 parseError->offset = 0;
440 parseError->preContext[0] = 0;
441 parseError->postContext[0] = 0;
442
443
444 // first we want to pick stuff out of short string.
445 // we'll end up with an UCA version, locale and a bunch of
446 // settings
447
448 // analyse the string in order to get everything we need.
449 CollatorSpec s;
450 ucol_sit_readSpecs(&s, definition, parseError, status);
451 ucol_sit_calculateWholeLocale(&s, *status);
452
453 CharString buffer = ulocimp_canonicalizeulocimp_canonicalize_77(s.locale.toStringPiece(), *status);
454
455 UResourceBundle *b = ures_openures_open_77(U_ICUDATA_COLL"icudt" "77" "l" "-" "coll", buffer.data(), status);
456 /* we try to find stuff from keyword */
457 UResourceBundle *collations = ures_getByKeyures_getByKey_77(b, "collations", nullptr, status);
458 UResourceBundle *collElem = nullptr;
459 // if there is a keyword, we pick it up and try to get elements
460 CharString keyBuffer = ulocimp_getKeywordValueulocimp_getKeywordValue_77(buffer.data(), "collation", *status);
461 if(keyBuffer.isEmpty()) {
462 // no keyword
463 // we try to find the default setting, which will give us the keyword value
464 UResourceBundle *defaultColl = ures_getByKeyWithFallbackures_getByKeyWithFallback_77(collations, "default", nullptr, status);
465 if(U_SUCCESS(*status)) {
466 int32_t defaultKeyLen = 0;
467 const char16_t *defaultKey = ures_getStringures_getString_77(defaultColl, &defaultKeyLen, status);
468 keyBuffer.appendInvariantChars(defaultKey, defaultKeyLen, *status);
469 } else {
470 *status = U_INTERNAL_PROGRAM_ERROR;
471 return;
472 }
473 ures_closeures_close_77(defaultColl);
474 }
475 collElem = ures_getByKeyWithFallbackures_getByKeyWithFallback_77(collations, keyBuffer.data(), collElem, status);
476 ures_closeures_close_77(collElem);
477 ures_closeures_close_77(collations);
478 ures_closeures_close_77(b);
479}
480
481
482U_CAPIextern "C" UCollator* U_EXPORT2
483ucol_openFromShortStringucol_openFromShortString_77( const char *definition,
484 UBool forceDefaults,
485 UParseError *parseError,
486 UErrorCode *status)
487{
488 UTRACE_ENTRY_OC(UTRACE_UCOL_OPEN_FROM_SHORT_STRING);
489 UTRACE_DATA1(UTRACE_INFO, "short string = \"%s\"", definition);
490
491 if (U_FAILURE(*status)) return nullptr;
492
493 UParseError internalParseError;
494
495 if(!parseError) {
496 parseError = &internalParseError;
497 }
498 parseError->line = 0;
499 parseError->offset = 0;
500 parseError->preContext[0] = 0;
501 parseError->postContext[0] = 0;
502
503
504 // first we want to pick stuff out of short string.
505 // we'll end up with an UCA version, locale and a bunch of
506 // settings
507
508 // analyse the string in order to get everything we need.
509 const char *string = definition;
510 CollatorSpec s;
511 string = ucol_sit_readSpecs(&s, definition, parseError, status);
512 ucol_sit_calculateWholeLocale(&s, *status);
513
514#ifdef UCOL_TRACE_SIT
515 fprintf(stderrstderr, "DEF %s, DATA %s, ERR %s\n", definition, s.locale.data(), u_errorNameu_errorName_77(*status));
516#endif
517 CharString buffer = ulocimp_canonicalizeulocimp_canonicalize_77(s.locale.toStringPiece(), *status);
518
519 UCollator *result = ucol_openucol_open_77(buffer.data(), status);
520 int32_t i = 0;
521
522 for(i = 0; i < UCOL_ATTRIBUTE_COUNT; i++) {
523 if(s.options[i] != UCOL_DEFAULT) {
524 if(forceDefaults || ucol_getAttributeucol_getAttribute_77(result, (UColAttribute)i, status) != s.options[i]) {
525 ucol_setAttributeucol_setAttribute_77(result, (UColAttribute)i, s.options[i], status);
526 }
527
528 if(U_FAILURE(*status)) {
529 parseError->offset = (int32_t)(string - definition);
530 ucol_closeucol_close_77(result);
531 return nullptr;
532 }
533
534 }
535 }
536 if(s.variableTopSet) {
537 if(s.variableTopString[0]) {
538 ucol_setVariableTopucol_setVariableTop_77(result, s.variableTopString, s.variableTopStringLen, status);
539 } else { // we set by value, using 'B'
540 ucol_restoreVariableTopucol_restoreVariableTop_77(result, s.variableTopValue, status);
541 }
542 }
543
544
545 if(U_FAILURE(*status)) { // here it can only be a bogus value
546 ucol_closeucol_close_77(result);
547 result = nullptr;
548 }
549
550 UTRACE_EXIT_PTR_STATUS(result, *status);
551 return result;
552}
553
554
555U_CAPIextern "C" int32_t U_EXPORT2
556ucol_getShortDefinitionStringucol_getShortDefinitionString_77(const UCollator *coll,
557 const char *locale,
558 char *dst,
559 int32_t capacity,
560 UErrorCode *status)
561{
562 if(U_FAILURE(*status)) return 0;
563 if(coll == nullptr) {
564 *status = U_ILLEGAL_ARGUMENT_ERROR;
565 return 0;
566 }
567 return ((icu::Collator*)coll)->internalGetShortDefinitionString(locale,dst,capacity,*status);
568}
569
570U_CAPIextern "C" int32_t U_EXPORT2
571ucol_normalizeShortDefinitionStringucol_normalizeShortDefinitionString_77(const char *definition,
572 char *destination,
573 int32_t capacity,
574 UParseError *parseError,
575 UErrorCode *status)
576{
577
578 if(U_FAILURE(*status)) {
1
Taking false branch
579 return 0;
580 }
581
582 if(destination) {
2
Assuming 'destination' is null
3
Taking false branch
583 uprv_memset(destination, 0, capacity*sizeof(char)):: memset(destination, 0, capacity*sizeof(char));
584 }
585
586 UParseError pe;
587 if(!parseError) {
4
Assuming 'parseError' is non-null
5
Taking false branch
588 parseError = &pe;
589 }
590
591 // validate
592 CollatorSpec s;
593 ucol_sit_readSpecs(&s, definition, parseError, status);
594 return ucol_sit_dumpSpecs(&s, destination, capacity, status);
6
Passing null pointer value via 2nd parameter 'destination'
7
Calling 'ucol_sit_dumpSpecs'
595}
596
597/**
598 * Get a set containing the contractions defined by the collator. The set includes
599 * both the UCA contractions and the contractions defined by the collator
600 * @param coll collator
601 * @param conts the set to hold the result
602 * @param status to hold the error code
603 * @return the size of the contraction set
604 */
605U_CAPIextern "C" int32_t U_EXPORT2
606ucol_getContractionsucol_getContractions_77( const UCollator *coll,
607 USet *contractions,
608 UErrorCode *status)
609{
610 ucol_getContractionsAndExpansionsucol_getContractionsAndExpansions_77(coll, contractions, nullptr, false, status);
611 return uset_getItemCountuset_getItemCount_77(contractions);
612}
613
614/**
615 * Get a set containing the expansions defined by the collator. The set includes
616 * both the UCA expansions and the expansions defined by the tailoring
617 * @param coll collator
618 * @param conts the set to hold the result
619 * @param addPrefixes add the prefix contextual elements to contractions
620 * @param status to hold the error code
621 *
622 * @draft ICU 3.4
623 */
624U_CAPIextern "C" void U_EXPORT2
625ucol_getContractionsAndExpansionsucol_getContractionsAndExpansions_77( const UCollator *coll,
626 USet *contractions,
627 USet *expansions,
628 UBool addPrefixes,
629 UErrorCode *status)
630{
631 if(U_FAILURE(*status)) {
632 return;
633 }
634 if(coll == nullptr) {
635 *status = U_ILLEGAL_ARGUMENT_ERROR;
636 return;
637 }
638 const icu::RuleBasedCollator *rbc = icu::RuleBasedCollator::rbcFromUCollator(coll);
639 if(rbc == nullptr) {
640 *status = U_UNSUPPORTED_ERROR;
641 return;
642 }
643 rbc->internalGetContractionsAndExpansions(
644 icu::UnicodeSet::fromUSet(contractions),
645 icu::UnicodeSet::fromUSet(expansions),
646 addPrefixes, *status);
647}
648#endif