Bug Summary

File:root/firefox-clang/intl/icu/source/i18n/dtfmtsym.cpp
Warning:line 2300, column 17
Forming reference to null pointer

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 dtfmtsym.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/dtfmtsym.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) 1997-2016, International Business Machines Corporation and *
6* others. All Rights Reserved. *
7*******************************************************************************
8*
9* File DTFMTSYM.CPP
10*
11* Modification History:
12*
13* Date Name Description
14* 02/19/97 aliu Converted from java.
15* 07/21/98 stephen Added getZoneIndex
16* Changed weekdays/short weekdays to be one-based
17* 06/14/99 stephen Removed SimpleDateFormat::fgTimeZoneDataSuffix
18* 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars
19* 03/27/00 weiv Keeping resource bundle around!
20* 06/30/05 emmons Added eraNames, narrow month/day, standalone context
21* 10/12/05 emmons Added setters for eraNames, month/day by width/context
22*******************************************************************************
23*/
24
25#include <utility>
26
27#include "unicode/utypes.h"
28
29#if !UCONFIG_NO_FORMATTING0
30#include "unicode/ustring.h"
31#include "unicode/localpointer.h"
32#include "unicode/dtfmtsym.h"
33#include "unicode/smpdtfmt.h"
34#include "unicode/msgfmt.h"
35#include "unicode/numsys.h"
36#include "unicode/tznames.h"
37#include "cpputils.h"
38#include "umutex.h"
39#include "cmemory.h"
40#include "cstring.h"
41#include "charstr.h"
42#include "dt_impl.h"
43#include "locbased.h"
44#include "gregoimp.h"
45#include "hash.h"
46#include "uassert.h"
47#include "uresimp.h"
48#include "ureslocs.h"
49#include "uvector.h"
50#include "shareddateformatsymbols.h"
51#include "unicode/calendar.h"
52#include "unifiedcache.h"
53
54// *****************************************************************************
55// class DateFormatSymbols
56// *****************************************************************************
57
58/**
59 * These are static arrays we use only in the case where we have no
60 * resource data.
61 */
62
63#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR0
64#define PATTERN_CHARS_LEN37 38
65#else
66#define PATTERN_CHARS_LEN37 37
67#endif
68
69/**
70 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
71 * locales use the same these unlocalized pattern characters.
72 */
73static const char16_t gPatternChars[] = {
74 // if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
75 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
76 // else:
77 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
78
79 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
80 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
81 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
82 0x55, 0x4F, 0x58, 0x78, 0x72, 0x62, 0x42,
83#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR0
84 0x3a,
85#endif
86 0
87};
88
89/**
90 * Map of each ASCII character to its corresponding index in the table above if
91 * it is a pattern character and -1 otherwise.
92 */
93static const int8_t gLookupPatternChars[] = {
94 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
95 //
96 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
97 // ! " # $ % & ' ( ) * + , - . /
98 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
99#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR0
100 // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
101 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1,
102#else
103 // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
104 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
105#endif
106 // @ A B C D E F G H I J K L M N O
107 -1, 22, 36, -1, 10, 9, 11, 0, 5, -1, -1, 16, 26, 2, -1, 31,
108 // P Q R S T U V W X Y Z [ \ ] ^ _
109 -1, 27, -1, 8, -1, 30, 29, 13, 32, 18, 23, -1, -1, -1, -1, -1,
110 // ` a b c d e f g h i j k l m n o
111 -1, 14, 35, 25, 3, 19, -1, 21, 15, -1, -1, 4, -1, 6, -1, -1,
112 // p q r s t u v w x y z { | } ~
113 -1, 28, 34, 7, -1, 20, 24, 12, 33, 1, 17, -1, -1, -1, -1, -1
114};
115
116//------------------------------------------------------
117// Strings of last resort. These are only used if we have no resource
118// files. They aren't designed for actual use, just for backup.
119
120// These are the month names and abbreviations of last resort.
121static const char16_t gLastResortMonthNames[13][3] =
122{
123 {0x0030, 0x0031, 0x0000}, /* "01" */
124 {0x0030, 0x0032, 0x0000}, /* "02" */
125 {0x0030, 0x0033, 0x0000}, /* "03" */
126 {0x0030, 0x0034, 0x0000}, /* "04" */
127 {0x0030, 0x0035, 0x0000}, /* "05" */
128 {0x0030, 0x0036, 0x0000}, /* "06" */
129 {0x0030, 0x0037, 0x0000}, /* "07" */
130 {0x0030, 0x0038, 0x0000}, /* "08" */
131 {0x0030, 0x0039, 0x0000}, /* "09" */
132 {0x0031, 0x0030, 0x0000}, /* "10" */
133 {0x0031, 0x0031, 0x0000}, /* "11" */
134 {0x0031, 0x0032, 0x0000}, /* "12" */
135 {0x0031, 0x0033, 0x0000} /* "13" */
136};
137
138// These are the weekday names and abbreviations of last resort.
139static const char16_t gLastResortDayNames[8][2] =
140{
141 {0x0030, 0x0000}, /* "0" */
142 {0x0031, 0x0000}, /* "1" */
143 {0x0032, 0x0000}, /* "2" */
144 {0x0033, 0x0000}, /* "3" */
145 {0x0034, 0x0000}, /* "4" */
146 {0x0035, 0x0000}, /* "5" */
147 {0x0036, 0x0000}, /* "6" */
148 {0x0037, 0x0000} /* "7" */
149};
150
151// These are the quarter names and abbreviations of last resort.
152static const char16_t gLastResortQuarters[4][2] =
153{
154 {0x0031, 0x0000}, /* "1" */
155 {0x0032, 0x0000}, /* "2" */
156 {0x0033, 0x0000}, /* "3" */
157 {0x0034, 0x0000}, /* "4" */
158};
159
160// These are the am/pm and BC/AD markers of last resort.
161static const char16_t gLastResortAmPmMarkers[2][3] =
162{
163 {0x0041, 0x004D, 0x0000}, /* "AM" */
164 {0x0050, 0x004D, 0x0000} /* "PM" */
165};
166
167static const char16_t gLastResortEras[2][3] =
168{
169 {0x0042, 0x0043, 0x0000}, /* "BC" */
170 {0x0041, 0x0044, 0x0000} /* "AD" */
171};
172
173/* Sizes for the last resort string arrays */
174typedef enum LastResortSize {
175 kMonthNum = 13,
176 kMonthLen = 3,
177
178 kDayNum = 8,
179 kDayLen = 2,
180
181 kAmPmNum = 2,
182 kAmPmLen = 3,
183
184 kQuarterNum = 4,
185 kQuarterLen = 2,
186
187 kEraNum = 2,
188 kEraLen = 3,
189
190 kZoneNum = 5,
191 kZoneLen = 4,
192
193 kGmtHourNum = 4,
194 kGmtHourLen = 10
195} LastResortSize;
196
197U_NAMESPACE_BEGINnamespace icu_77 {
198
199SharedDateFormatSymbols::~SharedDateFormatSymbols() {
200}
201
202template<> U_I18N_API
203const SharedDateFormatSymbols *
204 LocaleCacheKey<SharedDateFormatSymbols>::createObject(
205 const void * /*unusedContext*/, UErrorCode &status) const {
206 char type[256];
207 Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type)(int32_t)(sizeof(type)/sizeof((type)[0])), status);
208 if (U_FAILURE(status)) {
209 return nullptr;
210 }
211 SharedDateFormatSymbols *shared
212 = new SharedDateFormatSymbols(fLoc, type, status);
213 if (shared == nullptr) {
214 status = U_MEMORY_ALLOCATION_ERROR;
215 return nullptr;
216 }
217 if (U_FAILURE(status)) {
218 delete shared;
219 return nullptr;
220 }
221 shared->addRef();
222 return shared;
223}
224
225UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)UClassID DateFormatSymbols::getStaticClassID() { static char classID
= 0; return (UClassID)&classID; } UClassID DateFormatSymbols
::getDynamicClassID() const { return DateFormatSymbols::getStaticClassID
(); }
226
227#define kSUPPLEMENTAL"supplementalData" "supplementalData"
228
229/**
230 * These are the tags we expect to see in normal resource bundle files associated
231 * with a locale and calendar
232 */
233static const char gCalendarTag[]="calendar";
234static const char gGregorianTag[]="gregorian";
235static const char gErasTag[]="eras";
236static const char gCyclicNameSetsTag[]="cyclicNameSets";
237static const char gNameSetYearsTag[]="years";
238static const char gNameSetZodiacsTag[]="zodiacs";
239static const char gMonthNamesTag[]="monthNames";
240static const char gMonthPatternsTag[]="monthPatterns";
241static const char gDayNamesTag[]="dayNames";
242static const char gNamesWideTag[]="wide";
243static const char gNamesAbbrTag[]="abbreviated";
244static const char gNamesShortTag[]="short";
245static const char gNamesNarrowTag[]="narrow";
246static const char gNamesAllTag[]="all";
247static const char gNamesFormatTag[]="format";
248static const char gNamesStandaloneTag[]="stand-alone";
249static const char gNamesNumericTag[]="numeric";
250static const char gAmPmMarkersTag[]="AmPmMarkers";
251static const char gAmPmMarkersAbbrTag[]="AmPmMarkersAbbr";
252static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow";
253static const char gQuartersTag[]="quarters";
254static const char gNumberElementsTag[]="NumberElements";
255static const char gSymbolsTag[]="symbols";
256static const char gTimeSeparatorTag[]="timeSeparator";
257static const char gDayPeriodTag[]="dayPeriod";
258
259// static const char gZoneStringsTag[]="zoneStrings";
260
261// static const char gLocalPatternCharsTag[]="localPatternChars";
262
263static const char gContextTransformsTag[]="contextTransforms";
264
265/**
266 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
267 * Work around this.
268 */
269static inline UnicodeString* newUnicodeStringArray(size_t count) {
270 return new UnicodeString[count ? count : 1];
271}
272
273//------------------------------------------------------
274
275DateFormatSymbols * U_EXPORT2
276DateFormatSymbols::createForLocale(
277 const Locale& locale, UErrorCode &status) {
278 const SharedDateFormatSymbols *shared = nullptr;
279 UnifiedCache::getByLocale(locale, shared, status);
280 if (U_FAILURE(status)) {
281 return nullptr;
282 }
283 DateFormatSymbols *result = new DateFormatSymbols(shared->get());
284 shared->removeRef();
285 if (result == nullptr) {
286 status = U_MEMORY_ALLOCATION_ERROR;
287 return nullptr;
288 }
289 return result;
290}
291
292DateFormatSymbols::DateFormatSymbols(const Locale& locale,
293 UErrorCode& status)
294 : UObject()
295{
296 initializeData(locale, nullptr, status);
297}
298
299DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
300 : UObject()
301{
302 initializeData(Locale::getDefault(), nullptr, status, true);
303}
304
305
306DateFormatSymbols::DateFormatSymbols(const Locale& locale,
307 const char *type,
308 UErrorCode& status)
309 : UObject()
310{
311 initializeData(locale, type, status);
312}
313
314DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
315 : UObject()
316{
317 initializeData(Locale::getDefault(), type, status, true);
318}
319
320DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
321 : UObject(other)
322{
323 copyData(other);
324}
325
326void
327DateFormatSymbols::assignArray(UnicodeString*& dstArray,
328 int32_t& dstCount,
329 const UnicodeString* srcArray,
330 int32_t srcCount)
331{
332 // assignArray() is only called by copyData() and initializeData(), which in turn
333 // implements the copy constructor and the assignment operator.
334 // All strings in a DateFormatSymbols object are created in one of the following
335 // three ways that all allow to safely use UnicodeString::fastCopyFrom():
336 // - readonly-aliases from resource bundles
337 // - readonly-aliases or allocated strings from constants
338 // - safely cloned strings (with owned buffers) from setXYZ() functions
339 //
340 // Note that this is true for as long as DateFormatSymbols can be constructed
341 // only from a locale bundle or set via the cloning API,
342 // *and* for as long as all the strings are in *private* fields, preventing
343 // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
344 if(srcArray == nullptr) {
345 // Do not attempt to copy bogus input (which will crash).
346 // Note that this assignArray method already had the potential to return a null dstArray;
347 // see handling below for "if(dstArray != nullptr)".
348 dstCount = 0;
349 dstArray = nullptr;
350 return;
351 }
352 dstCount = srcCount;
353 dstArray = newUnicodeStringArray(srcCount);
354 if(dstArray != nullptr) {
355 int32_t i;
356 for(i=0; i<srcCount; ++i) {
357 dstArray[i].fastCopyFrom(srcArray[i]);
358 }
359 }
360}
361
362/**
363 * Create a copy, in fZoneStrings, of the given zone strings array. The
364 * member variables fZoneStringsRowCount and fZoneStringsColCount should
365 * be set already by the caller.
366 */
367void
368DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
369{
370 int32_t row, col;
371 UBool failed = false;
372
373 fZoneStrings = static_cast<UnicodeString**>(uprv_mallocuprv_malloc_77(fZoneStringsRowCount * sizeof(UnicodeString*)));
374 if (fZoneStrings != nullptr) {
375 for (row=0; row<fZoneStringsRowCount; ++row)
376 {
377 fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
378 if (fZoneStrings[row] == nullptr) {
379 failed = true;
380 break;
381 }
382 for (col=0; col<fZoneStringsColCount; ++col) {
383 // fastCopyFrom() - see assignArray comments
384 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
385 }
386 }
387 }
388 // If memory allocation failed, roll back and delete fZoneStrings
389 if (failed) {
390 for (int i = row; i >= 0; i--) {
391 delete[] fZoneStrings[i];
392 }
393 uprv_freeuprv_free_77(fZoneStrings);
394 fZoneStrings = nullptr;
395 }
396}
397
398/**
399 * Copy all of the other's data to this.
400 */
401void
402DateFormatSymbols::copyData(const DateFormatSymbols& other) {
403 UErrorCode status = U_ZERO_ERROR;
404 U_LOCALE_BASED(locBased, *this)LocaleBased locBased((*this).validLocale, (*this).actualLocale
)
;
405 locBased.setLocaleIDs(other.validLocale, other.actualLocale, status);
406 U_ASSERT(U_SUCCESS(status))(static_cast <bool> (U_SUCCESS(status)) ? void (0) : __assert_fail
("U_SUCCESS(status)", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
407 assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
408 assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
409 assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
410 assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
411 assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
412 assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
413 assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
414 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
415 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
416 assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
417 assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
418 assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
419 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
420 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
421 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
422 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
423 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
424 assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
425 assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
426 fTimeSeparator.fastCopyFrom(other.fTimeSeparator); // fastCopyFrom() - see assignArray comments
427 assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
428 assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
429 assignArray(fNarrowQuarters, fNarrowQuartersCount, other.fNarrowQuarters, other.fNarrowQuartersCount);
430 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
431 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
432 assignArray(fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, other.fStandaloneNarrowQuarters, other.fStandaloneNarrowQuartersCount);
433 assignArray(fWideDayPeriods, fWideDayPeriodsCount,
434 other.fWideDayPeriods, other.fWideDayPeriodsCount);
435 assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
436 other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
437 assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
438 other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
439 assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
440 other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
441 assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
442 other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
443 assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
444 other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
445 if (other.fLeapMonthPatterns != nullptr) {
446 assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
447 } else {
448 fLeapMonthPatterns = nullptr;
449 fLeapMonthPatternsCount = 0;
450 }
451 if (other.fShortYearNames != nullptr) {
452 assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
453 } else {
454 fShortYearNames = nullptr;
455 fShortYearNamesCount = 0;
456 }
457 if (other.fShortZodiacNames != nullptr) {
458 assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
459 } else {
460 fShortZodiacNames = nullptr;
461 fShortZodiacNamesCount = 0;
462 }
463
464 if (other.fZoneStrings != nullptr) {
465 fZoneStringsColCount = other.fZoneStringsColCount;
466 fZoneStringsRowCount = other.fZoneStringsRowCount;
467 createZoneStrings((const UnicodeString**)other.fZoneStrings);
468
469 } else {
470 fZoneStrings = nullptr;
471 fZoneStringsColCount = 0;
472 fZoneStringsRowCount = 0;
473 }
474 fZSFLocale = other.fZSFLocale;
475 // Other zone strings data is created on demand
476 fLocaleZoneStrings = nullptr;
477
478 // fastCopyFrom() - see assignArray comments
479 fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
480
481 uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (fCapitalization != __null) ? void
(0) : __assert_fail ("fCapitalization != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); (
static_cast <bool> (other.fCapitalization != __null) ? void
(0) : __assert_fail ("other.fCapitalization != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(fCapitalization, other.fCapitalization
, sizeof(fCapitalization)); } while (false)
;
482}
483
484/**
485 * Assignment operator.
486 */
487DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
488{
489 if (this == &other) { return *this; } // self-assignment: no-op
490 dispose();
491 copyData(other);
492
493 return *this;
494}
495
496DateFormatSymbols::~DateFormatSymbols()
497{
498 dispose();
499 delete actualLocale;
500 delete validLocale;
501}
502
503void DateFormatSymbols::dispose()
504{
505 delete[] fEras;
506 delete[] fEraNames;
507 delete[] fNarrowEras;
508 delete[] fMonths;
509 delete[] fShortMonths;
510 delete[] fNarrowMonths;
511 delete[] fStandaloneMonths;
512 delete[] fStandaloneShortMonths;
513 delete[] fStandaloneNarrowMonths;
514 delete[] fWeekdays;
515 delete[] fShortWeekdays;
516 delete[] fShorterWeekdays;
517 delete[] fNarrowWeekdays;
518 delete[] fStandaloneWeekdays;
519 delete[] fStandaloneShortWeekdays;
520 delete[] fStandaloneShorterWeekdays;
521 delete[] fStandaloneNarrowWeekdays;
522 delete[] fAmPms;
523 delete[] fNarrowAmPms;
524 delete[] fQuarters;
525 delete[] fShortQuarters;
526 delete[] fNarrowQuarters;
527 delete[] fStandaloneQuarters;
528 delete[] fStandaloneShortQuarters;
529 delete[] fStandaloneNarrowQuarters;
530 delete[] fLeapMonthPatterns;
531 delete[] fShortYearNames;
532 delete[] fShortZodiacNames;
533 delete[] fAbbreviatedDayPeriods;
534 delete[] fWideDayPeriods;
535 delete[] fNarrowDayPeriods;
536 delete[] fStandaloneAbbreviatedDayPeriods;
537 delete[] fStandaloneWideDayPeriods;
538 delete[] fStandaloneNarrowDayPeriods;
539
540 delete actualLocale;
541 actualLocale = nullptr;
542 delete validLocale;
543 validLocale = nullptr;
544 disposeZoneStrings();
545}
546
547void DateFormatSymbols::disposeZoneStrings()
548{
549 if (fZoneStrings) {
550 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
551 delete[] fZoneStrings[row];
552 }
553 uprv_freeuprv_free_77(fZoneStrings);
554 }
555 if (fLocaleZoneStrings) {
556 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
557 delete[] fLocaleZoneStrings[row];
558 }
559 uprv_freeuprv_free_77(fLocaleZoneStrings);
560 }
561
562 fZoneStrings = nullptr;
563 fLocaleZoneStrings = nullptr;
564 fZoneStringsRowCount = 0;
565 fZoneStringsColCount = 0;
566}
567
568UBool
569DateFormatSymbols::arrayCompare(const UnicodeString* array1,
570 const UnicodeString* array2,
571 int32_t count)
572{
573 if (array1 == array2) return true;
574 while (count>0)
575 {
576 --count;
577 if (array1[count] != array2[count]) return false;
578 }
579 return true;
580}
581
582bool
583DateFormatSymbols::operator==(const DateFormatSymbols& other) const
584{
585 // First do cheap comparisons
586 if (this == &other) {
587 return true;
588 }
589 if (fErasCount == other.fErasCount &&
590 fEraNamesCount == other.fEraNamesCount &&
591 fNarrowErasCount == other.fNarrowErasCount &&
592 fMonthsCount == other.fMonthsCount &&
593 fShortMonthsCount == other.fShortMonthsCount &&
594 fNarrowMonthsCount == other.fNarrowMonthsCount &&
595 fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
596 fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
597 fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
598 fWeekdaysCount == other.fWeekdaysCount &&
599 fShortWeekdaysCount == other.fShortWeekdaysCount &&
600 fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
601 fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
602 fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
603 fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
604 fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
605 fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
606 fAmPmsCount == other.fAmPmsCount &&
607 fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
608 fQuartersCount == other.fQuartersCount &&
609 fShortQuartersCount == other.fShortQuartersCount &&
610 fNarrowQuartersCount == other.fNarrowQuartersCount &&
611 fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
612 fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
613 fStandaloneNarrowQuartersCount == other.fStandaloneNarrowQuartersCount &&
614 fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
615 fShortYearNamesCount == other.fShortYearNamesCount &&
616 fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
617 fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
618 fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
619 fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
620 fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
621 fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
622 fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
623 (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization)):: memcmp(fCapitalization, other.fCapitalization,sizeof(fCapitalization
))
==0))
624 {
625 // Now compare the arrays themselves
626 if (arrayCompare(fEras, other.fEras, fErasCount) &&
627 arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
628 arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
629 arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
630 arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
631 arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
632 arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
633 arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
634 arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
635 arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
636 arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
637 arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
638 arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
639 arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
640 arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
641 arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
642 arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
643 arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
644 arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
645 fTimeSeparator == other.fTimeSeparator &&
646 arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
647 arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
648 arrayCompare(fNarrowQuarters, other.fNarrowQuarters, fNarrowQuartersCount) &&
649 arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
650 arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
651 arrayCompare(fStandaloneNarrowQuarters, other.fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount) &&
652 arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
653 arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
654 arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
655 arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
656 arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
657 arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
658 arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
659 fStandaloneAbbreviatedDayPeriodsCount) &&
660 arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
661 fStandaloneWideDayPeriodsCount) &&
662 arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
663 fStandaloneWideDayPeriodsCount))
664 {
665 // Compare the contents of fZoneStrings
666 if (fZoneStrings == nullptr && other.fZoneStrings == nullptr) {
667 if (fZSFLocale == other.fZSFLocale) {
668 return true;
669 }
670 } else if (fZoneStrings != nullptr && other.fZoneStrings != nullptr) {
671 if (fZoneStringsRowCount == other.fZoneStringsRowCount
672 && fZoneStringsColCount == other.fZoneStringsColCount) {
673 bool cmpres = true;
674 for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
675 cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
676 }
677 return cmpres;
678 }
679 }
680 return false;
681 }
682 }
683 return false;
684}
685
686//------------------------------------------------------
687
688const UnicodeString*
689DateFormatSymbols::getEras(int32_t &count) const
690{
691 count = fErasCount;
692 return fEras;
693}
694
695const UnicodeString*
696DateFormatSymbols::getEraNames(int32_t &count) const
697{
698 count = fEraNamesCount;
699 return fEraNames;
700}
701
702const UnicodeString*
703DateFormatSymbols::getNarrowEras(int32_t &count) const
704{
705 count = fNarrowErasCount;
706 return fNarrowEras;
707}
708
709const UnicodeString*
710DateFormatSymbols::getMonths(int32_t &count) const
711{
712 count = fMonthsCount;
713 return fMonths;
714}
715
716const UnicodeString*
717DateFormatSymbols::getShortMonths(int32_t &count) const
718{
719 count = fShortMonthsCount;
720 return fShortMonths;
721}
722
723const UnicodeString*
724DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
725{
726 UnicodeString *returnValue = nullptr;
727
728 switch (context) {
729 case FORMAT :
730 switch(width) {
731 case WIDE :
732 count = fMonthsCount;
733 returnValue = fMonths;
734 break;
735 case ABBREVIATED :
736 case SHORT : // no month data for this, defaults to ABBREVIATED
737 count = fShortMonthsCount;
738 returnValue = fShortMonths;
739 break;
740 case NARROW :
741 count = fNarrowMonthsCount;
742 returnValue = fNarrowMonths;
743 break;
744 case DT_WIDTH_COUNT :
745 break;
746 }
747 break;
748 case STANDALONE :
749 switch(width) {
750 case WIDE :
751 count = fStandaloneMonthsCount;
752 returnValue = fStandaloneMonths;
753 break;
754 case ABBREVIATED :
755 case SHORT : // no month data for this, defaults to ABBREVIATED
756 count = fStandaloneShortMonthsCount;
757 returnValue = fStandaloneShortMonths;
758 break;
759 case NARROW :
760 count = fStandaloneNarrowMonthsCount;
761 returnValue = fStandaloneNarrowMonths;
762 break;
763 case DT_WIDTH_COUNT :
764 break;
765 }
766 break;
767 case DT_CONTEXT_COUNT :
768 break;
769 }
770 return returnValue;
771}
772
773const UnicodeString*
774DateFormatSymbols::getWeekdays(int32_t &count) const
775{
776 count = fWeekdaysCount;
777 return fWeekdays;
778}
779
780const UnicodeString*
781DateFormatSymbols::getShortWeekdays(int32_t &count) const
782{
783 count = fShortWeekdaysCount;
784 return fShortWeekdays;
785}
786
787const UnicodeString*
788DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
789{
790 UnicodeString *returnValue = nullptr;
791 switch (context) {
792 case FORMAT :
793 switch(width) {
794 case WIDE :
795 count = fWeekdaysCount;
796 returnValue = fWeekdays;
797 break;
798 case ABBREVIATED :
799 count = fShortWeekdaysCount;
800 returnValue = fShortWeekdays;
801 break;
802 case SHORT :
803 count = fShorterWeekdaysCount;
804 returnValue = fShorterWeekdays;
805 break;
806 case NARROW :
807 count = fNarrowWeekdaysCount;
808 returnValue = fNarrowWeekdays;
809 break;
810 case DT_WIDTH_COUNT :
811 break;
812 }
813 break;
814 case STANDALONE :
815 switch(width) {
816 case WIDE :
817 count = fStandaloneWeekdaysCount;
818 returnValue = fStandaloneWeekdays;
819 break;
820 case ABBREVIATED :
821 count = fStandaloneShortWeekdaysCount;
822 returnValue = fStandaloneShortWeekdays;
823 break;
824 case SHORT :
825 count = fStandaloneShorterWeekdaysCount;
826 returnValue = fStandaloneShorterWeekdays;
827 break;
828 case NARROW :
829 count = fStandaloneNarrowWeekdaysCount;
830 returnValue = fStandaloneNarrowWeekdays;
831 break;
832 case DT_WIDTH_COUNT :
833 break;
834 }
835 break;
836 case DT_CONTEXT_COUNT :
837 break;
838 }
839 return returnValue;
840}
841
842const UnicodeString*
843DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
844{
845 UnicodeString *returnValue = nullptr;
846
847 switch (context) {
848 case FORMAT :
849 switch(width) {
850 case WIDE :
851 count = fQuartersCount;
852 returnValue = fQuarters;
853 break;
854 case ABBREVIATED :
855 case SHORT : // no quarter data for this, defaults to ABBREVIATED
856 count = fShortQuartersCount;
857 returnValue = fShortQuarters;
858 break;
859 case NARROW :
860 count = fNarrowQuartersCount;
861 returnValue = fNarrowQuarters;
862 break;
863 case DT_WIDTH_COUNT :
864 break;
865 }
866 break;
867 case STANDALONE :
868 switch(width) {
869 case WIDE :
870 count = fStandaloneQuartersCount;
871 returnValue = fStandaloneQuarters;
872 break;
873 case ABBREVIATED :
874 case SHORT : // no quarter data for this, defaults to ABBREVIATED
875 count = fStandaloneShortQuartersCount;
876 returnValue = fStandaloneShortQuarters;
877 break;
878 case NARROW :
879 count = fStandaloneNarrowQuartersCount;
880 returnValue = fStandaloneNarrowQuarters;
881 break;
882 case DT_WIDTH_COUNT :
883 break;
884 }
885 break;
886 case DT_CONTEXT_COUNT :
887 break;
888 }
889 return returnValue;
890}
891
892UnicodeString&
893DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
894{
895 // fastCopyFrom() - see assignArray comments
896 return result.fastCopyFrom(fTimeSeparator);
897}
898
899const UnicodeString*
900DateFormatSymbols::getAmPmStrings(int32_t &count) const
901{
902 count = fAmPmsCount;
903 return fAmPms;
904}
905
906const UnicodeString*
907DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
908{
909 count = fLeapMonthPatternsCount;
910 return fLeapMonthPatterns;
911}
912
913const UnicodeString*
914DateFormatSymbols::getYearNames(int32_t& count,
915 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
916{
917 count = fShortYearNamesCount;
918 return fShortYearNames;
919}
920
921void
922DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
923 DtContextType context, DtWidthType width)
924{
925 if (context == FORMAT && width == ABBREVIATED) {
926 delete[] fShortYearNames;
927 fShortYearNames = newUnicodeStringArray(count);
928 uprv_arrayCopy(yearNames, fShortYearNames, count);
929 fShortYearNamesCount = count;
930 }
931}
932
933const UnicodeString*
934DateFormatSymbols::getZodiacNames(int32_t& count,
935 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
936{
937 count = fShortZodiacNamesCount;
938 return fShortZodiacNames;
939}
940
941void
942DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
943 DtContextType context, DtWidthType width)
944{
945 if (context == FORMAT && width == ABBREVIATED) {
946 delete[] fShortZodiacNames;
947 fShortZodiacNames = newUnicodeStringArray(count);
948 uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
949 fShortZodiacNamesCount = count;
950 }
951}
952
953//------------------------------------------------------
954
955void
956DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
957{
958 // delete the old list if we own it
959 delete[] fEras;
960
961 // we always own the new list, which we create here (we duplicate rather
962 // than adopting the list passed in)
963 fEras = newUnicodeStringArray(count);
964 uprv_arrayCopy(erasArray,fEras, count);
965 fErasCount = count;
966}
967
968void
969DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
970{
971 // delete the old list if we own it
972 delete[] fEraNames;
973
974 // we always own the new list, which we create here (we duplicate rather
975 // than adopting the list passed in)
976 fEraNames = newUnicodeStringArray(count);
977 uprv_arrayCopy(eraNamesArray,fEraNames, count);
978 fEraNamesCount = count;
979}
980
981void
982DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
983{
984 // delete the old list if we own it
985 delete[] fNarrowEras;
986
987 // we always own the new list, which we create here (we duplicate rather
988 // than adopting the list passed in)
989 fNarrowEras = newUnicodeStringArray(count);
990 uprv_arrayCopy(narrowErasArray,fNarrowEras, count);
991 fNarrowErasCount = count;
992}
993
994void
995DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
996{
997 // delete the old list if we own it
998 delete[] fMonths;
999
1000 // we always own the new list, which we create here (we duplicate rather
1001 // than adopting the list passed in)
1002 fMonths = newUnicodeStringArray(count);
1003 uprv_arrayCopy( monthsArray,fMonths,count);
1004 fMonthsCount = count;
1005}
1006
1007void
1008DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
1009{
1010 // delete the old list if we own it
1011 delete[] fShortMonths;
1012
1013 // we always own the new list, which we create here (we duplicate rather
1014 // than adopting the list passed in)
1015 fShortMonths = newUnicodeStringArray(count);
1016 uprv_arrayCopy(shortMonthsArray,fShortMonths, count);
1017 fShortMonthsCount = count;
1018}
1019
1020void
1021DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
1022{
1023 // delete the old list if we own it
1024 // we always own the new list, which we create here (we duplicate rather
1025 // than adopting the list passed in)
1026
1027 switch (context) {
1028 case FORMAT :
1029 switch (width) {
1030 case WIDE :
1031 delete[] fMonths;
1032 fMonths = newUnicodeStringArray(count);
1033 uprv_arrayCopy( monthsArray,fMonths,count);
1034 fMonthsCount = count;
1035 break;
1036 case ABBREVIATED :
1037 delete[] fShortMonths;
1038 fShortMonths = newUnicodeStringArray(count);
1039 uprv_arrayCopy( monthsArray,fShortMonths,count);
1040 fShortMonthsCount = count;
1041 break;
1042 case NARROW :
1043 delete[] fNarrowMonths;
1044 fNarrowMonths = newUnicodeStringArray(count);
1045 uprv_arrayCopy( monthsArray,fNarrowMonths,count);
1046 fNarrowMonthsCount = count;
1047 break;
1048 default :
1049 break;
1050 }
1051 break;
1052 case STANDALONE :
1053 switch (width) {
1054 case WIDE :
1055 delete[] fStandaloneMonths;
1056 fStandaloneMonths = newUnicodeStringArray(count);
1057 uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
1058 fStandaloneMonthsCount = count;
1059 break;
1060 case ABBREVIATED :
1061 delete[] fStandaloneShortMonths;
1062 fStandaloneShortMonths = newUnicodeStringArray(count);
1063 uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
1064 fStandaloneShortMonthsCount = count;
1065 break;
1066 case NARROW :
1067 delete[] fStandaloneNarrowMonths;
1068 fStandaloneNarrowMonths = newUnicodeStringArray(count);
1069 uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
1070 fStandaloneNarrowMonthsCount = count;
1071 break;
1072 default :
1073 break;
1074 }
1075 break;
1076 case DT_CONTEXT_COUNT :
1077 break;
1078 }
1079}
1080
1081void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
1082{
1083 // delete the old list if we own it
1084 delete[] fWeekdays;
1085
1086 // we always own the new list, which we create here (we duplicate rather
1087 // than adopting the list passed in)
1088 fWeekdays = newUnicodeStringArray(count);
1089 uprv_arrayCopy(weekdaysArray,fWeekdays,count);
1090 fWeekdaysCount = count;
1091}
1092
1093void
1094DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
1095{
1096 // delete the old list if we own it
1097 delete[] fShortWeekdays;
1098
1099 // we always own the new list, which we create here (we duplicate rather
1100 // than adopting the list passed in)
1101 fShortWeekdays = newUnicodeStringArray(count);
1102 uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
1103 fShortWeekdaysCount = count;
1104}
1105
1106void
1107DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
1108{
1109 // delete the old list if we own it
1110 // we always own the new list, which we create here (we duplicate rather
1111 // than adopting the list passed in)
1112
1113 switch (context) {
1114 case FORMAT :
1115 switch (width) {
1116 case WIDE :
1117 delete[] fWeekdays;
1118 fWeekdays = newUnicodeStringArray(count);
1119 uprv_arrayCopy(weekdaysArray, fWeekdays, count);
1120 fWeekdaysCount = count;
1121 break;
1122 case ABBREVIATED :
1123 delete[] fShortWeekdays;
1124 fShortWeekdays = newUnicodeStringArray(count);
1125 uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
1126 fShortWeekdaysCount = count;
1127 break;
1128 case SHORT :
1129 delete[] fShorterWeekdays;
1130 fShorterWeekdays = newUnicodeStringArray(count);
1131 uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
1132 fShorterWeekdaysCount = count;
1133 break;
1134 case NARROW :
1135 delete[] fNarrowWeekdays;
1136 fNarrowWeekdays = newUnicodeStringArray(count);
1137 uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
1138 fNarrowWeekdaysCount = count;
1139 break;
1140 case DT_WIDTH_COUNT :
1141 break;
1142 }
1143 break;
1144 case STANDALONE :
1145 switch (width) {
1146 case WIDE :
1147 delete[] fStandaloneWeekdays;
1148 fStandaloneWeekdays = newUnicodeStringArray(count);
1149 uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
1150 fStandaloneWeekdaysCount = count;
1151 break;
1152 case ABBREVIATED :
1153 delete[] fStandaloneShortWeekdays;
1154 fStandaloneShortWeekdays = newUnicodeStringArray(count);
1155 uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
1156 fStandaloneShortWeekdaysCount = count;
1157 break;
1158 case SHORT :
1159 delete[] fStandaloneShorterWeekdays;
1160 fStandaloneShorterWeekdays = newUnicodeStringArray(count);
1161 uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
1162 fStandaloneShorterWeekdaysCount = count;
1163 break;
1164 case NARROW :
1165 delete[] fStandaloneNarrowWeekdays;
1166 fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
1167 uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
1168 fStandaloneNarrowWeekdaysCount = count;
1169 break;
1170 case DT_WIDTH_COUNT :
1171 break;
1172 }
1173 break;
1174 case DT_CONTEXT_COUNT :
1175 break;
1176 }
1177}
1178
1179void
1180DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
1181{
1182 // delete the old list if we own it
1183 // we always own the new list, which we create here (we duplicate rather
1184 // than adopting the list passed in)
1185
1186 switch (context) {
1187 case FORMAT :
1188 switch (width) {
1189 case WIDE :
1190 delete[] fQuarters;
1191 fQuarters = newUnicodeStringArray(count);
1192 uprv_arrayCopy( quartersArray,fQuarters,count);
1193 fQuartersCount = count;
1194 break;
1195 case ABBREVIATED :
1196 delete[] fShortQuarters;
1197 fShortQuarters = newUnicodeStringArray(count);
1198 uprv_arrayCopy( quartersArray,fShortQuarters,count);
1199 fShortQuartersCount = count;
1200 break;
1201 case NARROW :
1202 delete[] fNarrowQuarters;
1203 fNarrowQuarters = newUnicodeStringArray(count);
1204 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1205 fNarrowQuartersCount = count;
1206 break;
1207 default :
1208 break;
1209 }
1210 break;
1211 case STANDALONE :
1212 switch (width) {
1213 case WIDE :
1214 delete[] fStandaloneQuarters;
1215 fStandaloneQuarters = newUnicodeStringArray(count);
1216 uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
1217 fStandaloneQuartersCount = count;
1218 break;
1219 case ABBREVIATED :
1220 delete[] fStandaloneShortQuarters;
1221 fStandaloneShortQuarters = newUnicodeStringArray(count);
1222 uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
1223 fStandaloneShortQuartersCount = count;
1224 break;
1225 case NARROW :
1226 delete[] fStandaloneNarrowQuarters;
1227 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1228 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1229 fStandaloneNarrowQuartersCount = count;
1230 break;
1231 default :
1232 break;
1233 }
1234 break;
1235 case DT_CONTEXT_COUNT :
1236 break;
1237 }
1238}
1239
1240void
1241DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
1242{
1243 // delete the old list if we own it
1244 delete[] fAmPms;
1245
1246 // we always own the new list, which we create here (we duplicate rather
1247 // than adopting the list passed in)
1248 fAmPms = newUnicodeStringArray(count);
1249 uprv_arrayCopy(amPmsArray,fAmPms,count);
1250 fAmPmsCount = count;
1251}
1252
1253void
1254DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
1255{
1256 fTimeSeparator = newTimeSeparator;
1257}
1258
1259const UnicodeString**
1260DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
1261{
1262 const UnicodeString **result = nullptr;
1263 static UMutex LOCK;
1264
1265 umtx_lockumtx_lock_77(&LOCK);
1266 if (fZoneStrings == nullptr) {
1267 if (fLocaleZoneStrings == nullptr) {
1268 const_cast<DateFormatSymbols*>(this)->initZoneStringsArray();
1269 }
1270 result = (const UnicodeString**)fLocaleZoneStrings;
1271 } else {
1272 result = (const UnicodeString**)fZoneStrings;
1273 }
1274 rowCount = fZoneStringsRowCount;
1275 columnCount = fZoneStringsColCount;
1276 umtx_unlockumtx_unlock_77(&LOCK);
1277
1278 return result;
1279}
1280
1281// For now, we include all zones
1282#define ZONE_SETUCAL_ZONE_TYPE_ANY UCAL_ZONE_TYPE_ANY
1283
1284// This code must be called within a synchronized block
1285void
1286DateFormatSymbols::initZoneStringsArray() {
1287 if (fZoneStrings != nullptr || fLocaleZoneStrings != nullptr) {
1288 return;
1289 }
1290
1291 UErrorCode status = U_ZERO_ERROR;
1292
1293 StringEnumeration *tzids = nullptr;
1294 UnicodeString ** zarray = nullptr;
1295 TimeZoneNames *tzNames = nullptr;
1296 int32_t rows = 0;
1297
1298 static const UTimeZoneNameType TYPES[] = {
1299 UTZNM_LONG_STANDARD, UTZNM_SHORT_STANDARD,
1300 UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_DAYLIGHT
1301 };
1302 static const int32_t NUM_TYPES = 4;
1303
1304 do { // dummy do-while
1305
1306 tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SETUCAL_ZONE_TYPE_ANY, nullptr, nullptr, status);
1307 rows = tzids->count(status);
1308 if (U_FAILURE(status)) {
1309 break;
1310 }
1311
1312 // Allocate array
1313 int32_t size = rows * sizeof(UnicodeString*);
1314 zarray = static_cast<UnicodeString**>(uprv_mallocuprv_malloc_77(size));
1315 if (zarray == nullptr) {
1316 status = U_MEMORY_ALLOCATION_ERROR;
1317 break;
1318 }
1319 uprv_memset(zarray, 0, size):: memset(zarray, 0, size);
1320
1321 tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1322 tzNames->loadAllDisplayNames(status);
1323 if (U_FAILURE(status)) { break; }
1324
1325 const UnicodeString *tzid;
1326 int32_t i = 0;
1327 UDate now = Calendar::getNow();
1328 UnicodeString tzDispName;
1329
1330 while ((tzid = tzids->snext(status)) != nullptr) {
1331 if (U_FAILURE(status)) {
1332 break;
1333 }
1334
1335 zarray[i] = new UnicodeString[5];
1336 if (zarray[i] == nullptr) {
1337 status = U_MEMORY_ALLOCATION_ERROR;
1338 break;
1339 }
1340
1341 zarray[i][0].setTo(*tzid);
1342 tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
1343 i++;
1344 }
1345
1346 } while (false);
1347
1348 if (U_FAILURE(status)) {
1349 if (zarray) {
1350 for (int32_t i = 0; i < rows; i++) {
1351 if (zarray[i]) {
1352 delete[] zarray[i];
1353 }
1354 }
1355 uprv_freeuprv_free_77(zarray);
1356 zarray = nullptr;
1357 }
1358 }
1359
1360 delete tzNames;
1361 delete tzids;
1362
1363 fLocaleZoneStrings = zarray;
1364 fZoneStringsRowCount = rows;
1365 fZoneStringsColCount = 1 + NUM_TYPES;
1366}
1367
1368void
1369DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1370{
1371 // since deleting a 2-d array is a pain in the butt, we offload that task to
1372 // a separate function
1373 disposeZoneStrings();
1374 // we always own the new list, which we create here (we duplicate rather
1375 // than adopting the list passed in)
1376 fZoneStringsRowCount = rowCount;
1377 fZoneStringsColCount = columnCount;
1378 createZoneStrings(const_cast<const UnicodeString**>(strings));
1379}
1380
1381//------------------------------------------------------
1382
1383const char16_t * U_EXPORT2
1384DateFormatSymbols::getPatternUChars()
1385{
1386 return gPatternChars;
1387}
1388
1389UDateFormatField U_EXPORT2
1390DateFormatSymbols::getPatternCharIndex(char16_t c) {
1391 if (c >= UPRV_LENGTHOF(gLookupPatternChars)(int32_t)(sizeof(gLookupPatternChars)/sizeof((gLookupPatternChars
)[0]))
) {
1392 return UDAT_FIELD_COUNT;
1393 }
1394 const auto idx = gLookupPatternChars[c];
1395 return idx == -1 ? UDAT_FIELD_COUNT : static_cast<UDateFormatField>(idx);
1396}
1397
1398static const uint64_t kNumericFieldsAlways =
1399 (static_cast<uint64_t>(1) << UDAT_YEAR_FIELD) | // y
1400 (static_cast<uint64_t>(1) << UDAT_DATE_FIELD) | // d
1401 (static_cast<uint64_t>(1) << UDAT_HOUR_OF_DAY1_FIELD) | // k
1402 (static_cast<uint64_t>(1) << UDAT_HOUR_OF_DAY0_FIELD) | // H
1403 (static_cast<uint64_t>(1) << UDAT_MINUTE_FIELD) | // m
1404 (static_cast<uint64_t>(1) << UDAT_SECOND_FIELD) | // s
1405 (static_cast<uint64_t>(1) << UDAT_FRACTIONAL_SECOND_FIELD) | // S
1406 (static_cast<uint64_t>(1) << UDAT_DAY_OF_YEAR_FIELD) | // D
1407 (static_cast<uint64_t>(1) << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) | // F
1408 (static_cast<uint64_t>(1) << UDAT_WEEK_OF_YEAR_FIELD) | // w
1409 (static_cast<uint64_t>(1) << UDAT_WEEK_OF_MONTH_FIELD) | // W
1410 (static_cast<uint64_t>(1) << UDAT_HOUR1_FIELD) | // h
1411 (static_cast<uint64_t>(1) << UDAT_HOUR0_FIELD) | // K
1412 (static_cast<uint64_t>(1) << UDAT_YEAR_WOY_FIELD) | // Y
1413 (static_cast<uint64_t>(1) << UDAT_EXTENDED_YEAR_FIELD) | // u
1414 (static_cast<uint64_t>(1) << UDAT_JULIAN_DAY_FIELD) | // g
1415 (static_cast<uint64_t>(1) << UDAT_MILLISECONDS_IN_DAY_FIELD) | // A
1416 (static_cast<uint64_t>(1) << UDAT_RELATED_YEAR_FIELD); // r
1417
1418static const uint64_t kNumericFieldsForCount12 =
1419 (static_cast<uint64_t>(1) << UDAT_MONTH_FIELD) | // M or MM
1420 (static_cast<uint64_t>(1) << UDAT_DOW_LOCAL_FIELD) | // e or ee
1421 (static_cast<uint64_t>(1) << UDAT_STANDALONE_DAY_FIELD) | // c or cc
1422 (static_cast<uint64_t>(1) << UDAT_STANDALONE_MONTH_FIELD) | // L or LL
1423 (static_cast<uint64_t>(1) << UDAT_QUARTER_FIELD) | // Q or QQ
1424 (static_cast<uint64_t>(1) << UDAT_STANDALONE_QUARTER_FIELD); // q or qq
1425
1426UBool U_EXPORT2
1427DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1428 if (f == UDAT_FIELD_COUNT) {
1429 return false;
1430 }
1431 uint64_t flag = static_cast<uint64_t>(1) << f;
1432 return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
1433}
1434
1435UBool U_EXPORT2
1436DateFormatSymbols::isNumericPatternChar(char16_t c, int32_t count) {
1437 return isNumericField(getPatternCharIndex(c), count);
1438}
1439
1440//------------------------------------------------------
1441
1442UnicodeString&
1443DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1444{
1445 // fastCopyFrom() - see assignArray comments
1446 return result.fastCopyFrom(fLocalPatternChars);
1447}
1448
1449//------------------------------------------------------
1450
1451void
1452DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1453{
1454 fLocalPatternChars = newLocalPatternChars;
1455}
1456
1457//------------------------------------------------------
1458
1459namespace {
1460
1461// Constants declarations
1462const char16_t kCalendarAliasPrefixUChar[] = {
1463 SOLIDUS((char16_t)0x002F), CAP_L((char16_t)0x004C), CAP_O((char16_t)0x004F), CAP_C((char16_t)0x0043), CAP_A((char16_t)0x0041), CAP_L((char16_t)0x004C), CAP_E((char16_t)0x0045), SOLIDUS((char16_t)0x002F),
1464 LOW_C((char16_t)0x0063), LOW_A((char16_t)0x0061), LOW_L((char16_t)0x006C), LOW_E((char16_t)0x0065), LOW_N((char16_t)0x006E), LOW_D((char16_t)0x0064), LOW_A((char16_t)0x0061), LOW_R((char16_t)0x0072), SOLIDUS((char16_t)0x002F)
1465};
1466const char16_t kGregorianTagUChar[] = {
1467 LOW_G((char16_t)0x0067), LOW_R((char16_t)0x0072), LOW_E((char16_t)0x0065), LOW_G((char16_t)0x0067), LOW_O((char16_t)0x006F), LOW_R((char16_t)0x0072), LOW_I((char16_t)0x0069), LOW_A((char16_t)0x0061), LOW_N((char16_t)0x006E)
1468};
1469const char16_t kVariantTagUChar[] = {
1470 PERCENT((char16_t)0x0025), LOW_V((char16_t)0x0076), LOW_A((char16_t)0x0061), LOW_R((char16_t)0x0072), LOW_I((char16_t)0x0069), LOW_A((char16_t)0x0061), LOW_N((char16_t)0x006E), LOW_T((char16_t)0x0074)
1471};
1472const char16_t kLeapTagUChar[] = {
1473 LOW_L((char16_t)0x006C), LOW_E((char16_t)0x0065), LOW_A((char16_t)0x0061), LOW_P((char16_t)0x0070)
1474};
1475const char16_t kCyclicNameSetsTagUChar[] = {
1476 LOW_C((char16_t)0x0063), LOW_Y((char16_t)0x0079), LOW_C((char16_t)0x0063), LOW_L((char16_t)0x006C), LOW_I((char16_t)0x0069), LOW_C((char16_t)0x0063), CAP_N((char16_t)0x004E), LOW_A((char16_t)0x0061), LOW_M((char16_t)0x006D), LOW_E((char16_t)0x0065), CAP_S((char16_t)0x0053), LOW_E((char16_t)0x0065), LOW_T((char16_t)0x0074), LOW_S((char16_t)0x0073)
1477};
1478const char16_t kYearsTagUChar[] = {
1479 SOLIDUS((char16_t)0x002F), LOW_Y((char16_t)0x0079), LOW_E((char16_t)0x0065), LOW_A((char16_t)0x0061), LOW_R((char16_t)0x0072), LOW_S((char16_t)0x0073)
1480};
1481const char16_t kZodiacsUChar[] = {
1482 SOLIDUS((char16_t)0x002F), LOW_Z((char16_t)0x007A), LOW_O((char16_t)0x006F), LOW_D((char16_t)0x0064), LOW_I((char16_t)0x0069), LOW_A((char16_t)0x0061), LOW_C((char16_t)0x0063), LOW_S((char16_t)0x0073)
1483};
1484const char16_t kDayPartsTagUChar[] = {
1485 SOLIDUS((char16_t)0x002F), LOW_D((char16_t)0x0064), LOW_A((char16_t)0x0061), LOW_Y((char16_t)0x0079), CAP_P((char16_t)0x0050), LOW_A((char16_t)0x0061), LOW_R((char16_t)0x0072), LOW_T((char16_t)0x0074), LOW_S((char16_t)0x0073)
1486};
1487const char16_t kFormatTagUChar[] = {
1488 SOLIDUS((char16_t)0x002F), LOW_F((char16_t)0x0066), LOW_O((char16_t)0x006F), LOW_R((char16_t)0x0072), LOW_M((char16_t)0x006D), LOW_A((char16_t)0x0061), LOW_T((char16_t)0x0074)
1489};
1490const char16_t kAbbrTagUChar[] = {
1491 SOLIDUS((char16_t)0x002F), LOW_A((char16_t)0x0061), LOW_B((char16_t)0x0062), LOW_B((char16_t)0x0062), LOW_R((char16_t)0x0072), LOW_E((char16_t)0x0065), LOW_V((char16_t)0x0076), LOW_I((char16_t)0x0069), LOW_A((char16_t)0x0061), LOW_T((char16_t)0x0074), LOW_E((char16_t)0x0065), LOW_D((char16_t)0x0064)
1492};
1493
1494// ResourceSink to enumerate all calendar resources
1495struct CalendarDataSink : public ResourceSink {
1496
1497 // Enum which specifies the type of alias received, or no alias
1498 enum AliasType {
1499 SAME_CALENDAR,
1500 DIFFERENT_CALENDAR,
1501 GREGORIAN,
1502 NONE
1503 };
1504
1505 // Data structures to store resources from the current resource bundle
1506 Hashtable arrays;
1507 Hashtable arraySizes;
1508 Hashtable maps;
1509 /**
1510 * Whenever there are aliases, the same object will be added twice to 'map'.
1511 * To avoid double deletion, 'maps' won't take ownership of the objects. Instead,
1512 * 'mapRefs' will own them and will delete them when CalendarDataSink is deleted.
1513 */
1514 MemoryPool<Hashtable> mapRefs;
1515
1516 // Paths and the aliases they point to
1517 UVector aliasPathPairs;
1518
1519 // Current and next calendar resource table which should be loaded
1520 UnicodeString currentCalendarType;
1521 UnicodeString nextCalendarType;
1522
1523 // Resources to visit when enumerating fallback calendars
1524 LocalPointer<UVector> resourcesToVisit;
1525
1526 // Alias' relative path populated whenever an alias is read
1527 UnicodeString aliasRelativePath;
1528
1529 // Initializes CalendarDataSink with default values
1530 CalendarDataSink(UErrorCode& status)
1531 : arrays(false, status), arraySizes(false, status), maps(false, status),
1532 mapRefs(),
1533 aliasPathPairs(uprv_deleteUObjectuprv_deleteUObject_77, uhash_compareUnicodeStringuhash_compareUnicodeString_77, status),
1534 currentCalendarType(), nextCalendarType(),
1535 resourcesToVisit(nullptr), aliasRelativePath() {
1536 if (U_FAILURE(status)) { return; }
1537 }
1538 virtual ~CalendarDataSink();
1539
1540 // Configure the CalendarSink to visit all the resources
1541 void visitAllResources() {
1542 resourcesToVisit.adoptInstead(nullptr);
1543 }
1544
1545 // Actions to be done before enumerating
1546 void preEnumerate(const UnicodeString &calendarType) {
1547 currentCalendarType = calendarType;
1548 nextCalendarType.setToBogus();
1549 aliasPathPairs.removeAllElements();
1550 }
1551
1552 virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) override {
1553 if (U_FAILURE(errorCode)) { return; }
1554 U_ASSERT(!currentCalendarType.isEmpty())(static_cast <bool> (!currentCalendarType.isEmpty()) ? void
(0) : __assert_fail ("!currentCalendarType.isEmpty()", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
1555
1556 // Stores the resources to visit on the next calendar.
1557 LocalPointer<UVector> resourcesToVisitNext(nullptr);
1558 ResourceTable calendarData = value.getTable(errorCode);
1559 if (U_FAILURE(errorCode)) { return; }
1560
1561 // Enumerate all resources for this calendar
1562 for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
1563 UnicodeString keyUString(key, -1, US_INVicu::UnicodeString::kInvariant);
1564
1565 // == Handle aliases ==
1566 AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
1567 if (U_FAILURE(errorCode)) { return; }
1568 if (aliasType == GREGORIAN) {
1569 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
1570 continue;
1571
1572 } else if (aliasType == DIFFERENT_CALENDAR) {
1573 // Whenever an alias to the next calendar (except gregorian) is encountered, register the
1574 // calendar type it's pointing to
1575 if (resourcesToVisitNext.isNull()) {
1576 resourcesToVisitNext
1577 .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObjectuprv_deleteUObject_77, uhash_compareUnicodeStringuhash_compareUnicodeString_77, errorCode),
1578 errorCode);
1579 if (U_FAILURE(errorCode)) { return; }
1580 }
1581 LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1582 resourcesToVisitNext->adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1583 if (U_FAILURE(errorCode)) { return; }
1584 continue;
1585
1586 } else if (aliasType == SAME_CALENDAR) {
1587 // Register same-calendar alias
1588 if (arrays.get(aliasRelativePath) == nullptr && maps.get(aliasRelativePath) == nullptr) {
1589 LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1590 aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1591 if (U_FAILURE(errorCode)) { return; }
1592 LocalPointer<UnicodeString> keyUStringCopy(keyUString.clone(), errorCode);
1593 aliasPathPairs.adoptElement(keyUStringCopy.orphan(), errorCode);
1594 if (U_FAILURE(errorCode)) { return; }
1595 }
1596 continue;
1597 }
1598
1599 // Only visit the resources that were referenced by an alias on the previous calendar
1600 // (AmPmMarkersAbbr is an exception).
1601 if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
1602 && uprv_strcmp(key, gAmPmMarkersAbbrTag):: strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
1603
1604 // == Handle data ==
1605 if (uprv_strcmp(key, gAmPmMarkersTag):: strcmp(key, gAmPmMarkersTag) == 0
1606 || uprv_strcmp(key, gAmPmMarkersAbbrTag):: strcmp(key, gAmPmMarkersAbbrTag) == 0
1607 || uprv_strcmp(key, gAmPmMarkersNarrowTag):: strcmp(key, gAmPmMarkersNarrowTag) == 0) {
1608 if (arrays.get(keyUString) == nullptr) {
1609 ResourceArray resourceArray = value.getArray(errorCode);
1610 int32_t arraySize = resourceArray.getSize();
1611 LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
1612 value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
1613 arrays.put(keyUString, stringArray.orphan(), errorCode);
1614 arraySizes.puti(keyUString, arraySize, errorCode);
1615 if (U_FAILURE(errorCode)) { return; }
1616 }
1617 } else if (uprv_strcmp(key, gErasTag):: strcmp(key, gErasTag) == 0
1618 || uprv_strcmp(key, gDayNamesTag):: strcmp(key, gDayNamesTag) == 0
1619 || uprv_strcmp(key, gMonthNamesTag):: strcmp(key, gMonthNamesTag) == 0
1620 || uprv_strcmp(key, gQuartersTag):: strcmp(key, gQuartersTag) == 0
1621 || uprv_strcmp(key, gDayPeriodTag):: strcmp(key, gDayPeriodTag) == 0
1622 || uprv_strcmp(key, gMonthPatternsTag):: strcmp(key, gMonthPatternsTag) == 0
1623 || uprv_strcmp(key, gCyclicNameSetsTag):: strcmp(key, gCyclicNameSetsTag) == 0) {
1624 processResource(keyUString, key, value, errorCode);
1625 }
1626 }
1627
1628 // Apply same-calendar aliases
1629 UBool modified;
1630 do {
1631 modified = false;
1632 for (int32_t i = 0; i < aliasPathPairs.size();) {
1633 UBool mod = false;
1634 UnicodeString* alias = static_cast<UnicodeString*>(aliasPathPairs[i]);
1635 UnicodeString *aliasArray;
1636 Hashtable *aliasMap;
1637 if ((aliasArray = static_cast<UnicodeString*>(arrays.get(*alias))) != nullptr) {
1638 UnicodeString* path = static_cast<UnicodeString*>(aliasPathPairs[i + 1]);
1639 if (arrays.get(*path) == nullptr) {
1640 // Clone the array
1641 int32_t aliasArraySize = arraySizes.geti(*alias);
1642 LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
1643 if (U_FAILURE(errorCode)) { return; }
1644 uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
1645 // Put the array on the 'arrays' map
1646 arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
1647 arraySizes.puti(*path, aliasArraySize, errorCode);
1648 }
1649 if (U_FAILURE(errorCode)) { return; }
1650 mod = true;
1651 } else if ((aliasMap = static_cast<Hashtable*>(maps.get(*alias))) != nullptr) {
1652 UnicodeString* path = static_cast<UnicodeString*>(aliasPathPairs[i + 1]);
1653 if (maps.get(*path) == nullptr) {
1654 maps.put(*path, aliasMap, errorCode);
1655 }
1656 if (U_FAILURE(errorCode)) { return; }
1657 mod = true;
1658 }
1659 if (mod) {
1660 aliasPathPairs.removeElementAt(i + 1);
1661 aliasPathPairs.removeElementAt(i);
1662 modified = true;
1663 } else {
1664 i += 2;
1665 }
1666 }
1667 } while (modified && !aliasPathPairs.isEmpty());
1668
1669 // Set the resources to visit on the next calendar
1670 if (!resourcesToVisitNext.isNull()) {
1671 resourcesToVisit = std::move(resourcesToVisitNext);
1672 }
1673 }
1674
1675 // Process the nested resource bundle tables
1676 void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
1677 if (U_FAILURE(errorCode)) return;
1678
1679 ResourceTable table = value.getTable(errorCode);
1680 if (U_FAILURE(errorCode)) return;
1681 Hashtable* stringMap = nullptr;
1682
1683 // Iterate over all the elements of the table and add them to the map
1684 for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
1685 UnicodeString keyUString(key, -1, US_INVicu::UnicodeString::kInvariant);
1686
1687 // Ignore '%variant' keys
1688 if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar)(int32_t)(sizeof(kVariantTagUChar)/sizeof((kVariantTagUChar)[
0]))
)) {
1689 continue;
1690 }
1691
1692 // == Handle String elements ==
1693 if (value.getType() == URES_STRING) {
1694 // We are on a leaf, store the map elements into the stringMap
1695 if (i == 0) {
1696 // mapRefs will keep ownership of 'stringMap':
1697 stringMap = mapRefs.create(false, errorCode);
1698 if (stringMap == nullptr) {
1699 errorCode = U_MEMORY_ALLOCATION_ERROR;
1700 return;
1701 }
1702 maps.put(path, stringMap, errorCode);
1703 if (U_FAILURE(errorCode)) { return; }
1704 stringMap->setValueDeleter(uprv_deleteUObjectuprv_deleteUObject_77);
1705 }
1706 U_ASSERT(stringMap != nullptr)(static_cast <bool> (stringMap != nullptr) ? void (0) :
__assert_fail ("stringMap != nullptr", __builtin_FILE (), __builtin_LINE
(), __extension__ __PRETTY_FUNCTION__))
;
1707 int32_t valueStringSize;
1708 const char16_t *valueString = value.getString(valueStringSize, errorCode);
1709 if (U_FAILURE(errorCode)) { return; }
1710 LocalPointer<UnicodeString> valueUString(new UnicodeString(true, valueString, valueStringSize), errorCode);
1711 stringMap->put(keyUString, valueUString.orphan(), errorCode);
1712 if (U_FAILURE(errorCode)) { return; }
1713 continue;
1714 }
1715 U_ASSERT(stringMap == nullptr)(static_cast <bool> (stringMap == nullptr) ? void (0) :
__assert_fail ("stringMap == nullptr", __builtin_FILE (), __builtin_LINE
(), __extension__ __PRETTY_FUNCTION__))
;
1716
1717 // Store the current path's length and append the current key to the path.
1718 int32_t pathLength = path.length();
1719 path.append(SOLIDUS((char16_t)0x002F)).append(keyUString);
1720
1721 // In cyclicNameSets ignore everything but years/format/abbreviated
1722 // and zodiacs/format/abbreviated
1723 if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar)(int32_t)(sizeof(kCyclicNameSetsTagUChar)/sizeof((kCyclicNameSetsTagUChar
)[0]))
)) {
1724 UBool skip = true;
1725 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar)(int32_t)(sizeof(kCyclicNameSetsTagUChar)/sizeof((kCyclicNameSetsTagUChar
)[0]))
;
1726 int32_t length = 0;
1727 if (startIndex == path.length()
1728 || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)(int32_t)(sizeof(kZodiacsUChar)/sizeof((kZodiacsUChar)[0]))), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)(int32_t)(sizeof(kZodiacsUChar)/sizeof((kZodiacsUChar)[0]))) == 0
1729 || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)(int32_t)(sizeof(kYearsTagUChar)/sizeof((kYearsTagUChar)[0]))), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)(int32_t)(sizeof(kYearsTagUChar)/sizeof((kYearsTagUChar)[0]))) == 0
1730 || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)(int32_t)(sizeof(kDayPartsTagUChar)/sizeof((kDayPartsTagUChar
)[0]))
), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)(int32_t)(sizeof(kDayPartsTagUChar)/sizeof((kDayPartsTagUChar
)[0]))
) == 0) {
1731 startIndex += length;
1732 length = 0;
1733 if (startIndex == path.length()
1734 || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)(int32_t)(sizeof(kFormatTagUChar)/sizeof((kFormatTagUChar)[0]
))
), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)(int32_t)(sizeof(kFormatTagUChar)/sizeof((kFormatTagUChar)[0]
))
) == 0) {
1735 startIndex += length;
1736 length = 0;
1737 if (startIndex == path.length()
1738 || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)(int32_t)(sizeof(kAbbrTagUChar)/sizeof((kAbbrTagUChar)[0]))), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)(int32_t)(sizeof(kAbbrTagUChar)/sizeof((kAbbrTagUChar)[0]))) == 0) {
1739 skip = false;
1740 }
1741 }
1742 }
1743 if (skip) {
1744 // Drop the latest key on the path and continue
1745 path.retainBetween(0, pathLength);
1746 continue;
1747 }
1748 }
1749
1750 // == Handle aliases ==
1751 if (arrays.get(path) != nullptr || maps.get(path) != nullptr) {
1752 // Drop the latest key on the path and continue
1753 path.retainBetween(0, pathLength);
1754 continue;
1755 }
1756
1757 AliasType aliasType = processAliasFromValue(path, value, errorCode);
1758 if (U_FAILURE(errorCode)) { return; }
1759 if (aliasType == SAME_CALENDAR) {
1760 // Store the alias path and the current path on aliasPathPairs
1761 LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1762 aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1763 if (U_FAILURE(errorCode)) { return; }
1764 LocalPointer<UnicodeString> pathCopy(path.clone(), errorCode);
1765 aliasPathPairs.adoptElement(pathCopy.orphan(), errorCode);
1766 if (U_FAILURE(errorCode)) { return; }
1767
1768 // Drop the latest key on the path and continue
1769 path.retainBetween(0, pathLength);
1770 continue;
1771 }
1772 U_ASSERT(aliasType == NONE)(static_cast <bool> (aliasType == NONE) ? void (0) : __assert_fail
("aliasType == NONE", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
1773
1774 // == Handle data ==
1775 if (value.getType() == URES_ARRAY) {
1776 // We are on a leaf, store the array
1777 ResourceArray rDataArray = value.getArray(errorCode);
1778 int32_t dataArraySize = rDataArray.getSize();
1779 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
1780 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
1781 arrays.put(path, dataArray.orphan(), errorCode);
1782 arraySizes.puti(path, dataArraySize, errorCode);
1783 if (U_FAILURE(errorCode)) { return; }
1784 } else if (value.getType() == URES_TABLE) {
1785 // We are not on a leaf, recursively process the subtable.
1786 processResource(path, key, value, errorCode);
1787 if (U_FAILURE(errorCode)) { return; }
1788 }
1789
1790 // Drop the latest key on the path
1791 path.retainBetween(0, pathLength);
1792 }
1793 }
1794
1795 // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
1796 AliasType processAliasFromValue(UnicodeString &currentRelativePath, ResourceValue &value,
1797 UErrorCode &errorCode) {
1798 if (U_FAILURE(errorCode)) { return NONE; }
1799
1800 if (value.getType() == URES_ALIAS) {
1801 int32_t aliasPathSize;
1802 const char16_t* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
1803 if (U_FAILURE(errorCode)) { return NONE; }
1804 UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
1805 const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar)(int32_t)(sizeof(kCalendarAliasPrefixUChar)/sizeof((kCalendarAliasPrefixUChar
)[0]))
;
1806 if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
1807 && aliasPath.length() > aliasPrefixLength) {
1808 int32_t typeLimit = aliasPath.indexOf(SOLIDUS((char16_t)0x002F), aliasPrefixLength);
1809 if (typeLimit > aliasPrefixLength) {
1810 const UnicodeString aliasCalendarType =
1811 aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
1812 aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
1813
1814 if (currentCalendarType == aliasCalendarType
1815 && currentRelativePath != aliasRelativePath) {
1816 // If we have an alias to the same calendar, the path to the resource must be different
1817 return SAME_CALENDAR;
1818
1819 } else if (currentCalendarType != aliasCalendarType
1820 && currentRelativePath == aliasRelativePath) {
1821 // If we have an alias to a different calendar, the path to the resource must be the same
1822 if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)(int32_t)(sizeof(kGregorianTagUChar)/sizeof((kGregorianTagUChar
)[0]))
) == 0) {
1823 return GREGORIAN;
1824 } else if (nextCalendarType.isBogus()) {
1825 nextCalendarType = aliasCalendarType;
1826 return DIFFERENT_CALENDAR;
1827 } else if (nextCalendarType == aliasCalendarType) {
1828 return DIFFERENT_CALENDAR;
1829 }
1830 }
1831 }
1832 }
1833 errorCode = U_INTERNAL_PROGRAM_ERROR;
1834 return NONE;
1835 }
1836 return NONE;
1837 }
1838
1839 // Deleter function to be used by 'arrays'
1840 static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
1841 delete[] static_cast<UnicodeString *>(uArray);
1842 }
1843};
1844// Virtual destructors have to be defined out of line
1845CalendarDataSink::~CalendarDataSink() {
1846 arrays.setValueDeleter(deleteUnicodeStringArray);
1847}
1848}
1849
1850//------------------------------------------------------
1851
1852static void
1853initField(UnicodeString **field, int32_t& length, const char16_t *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1854 if (U_SUCCESS(status)) {
1855 length = numStr;
1856 *field = newUnicodeStringArray(static_cast<size_t>(numStr));
1857 if (*field) {
1858 for(int32_t i = 0; i<length; i++) {
1859 // readonly aliases - all "data" strings are constant
1860 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1861 (*(field) + i)->setTo(true, data + (i * (static_cast<int32_t>(strLen))), -1);
1862 }
1863 }
1864 else {
1865 length = 0;
1866 status = U_MEMORY_ALLOCATION_ERROR;
1867 }
1868 }
1869}
1870
1871static void
1872initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
1873 if (U_SUCCESS(status)) {
1874 UnicodeString keyUString(key.data(), -1, US_INVicu::UnicodeString::kInvariant);
1875 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1876
1877 if (array != nullptr) {
1878 length = sink.arraySizes.geti(keyUString);
1879 *field = array;
1880 // DateFormatSymbols takes ownership of the array:
1881 sink.arrays.remove(keyUString);
1882 } else {
1883 length = 0;
1884 status = U_MISSING_RESOURCE_ERROR;
1885 }
1886 }
1887}
1888
1889static void
1890initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
1891 if (U_SUCCESS(status)) {
1892 UnicodeString keyUString(key.data(), -1, US_INVicu::UnicodeString::kInvariant);
1893 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1894
1895 if (array != nullptr) {
1896 int32_t arrayLength = sink.arraySizes.geti(keyUString);
1897 length = arrayLength + arrayOffset;
1898 *field = new UnicodeString[length];
1899 if (*field == nullptr) {
1900 status = U_MEMORY_ALLOCATION_ERROR;
1901 return;
1902 }
1903 uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
1904 } else {
1905 length = 0;
1906 status = U_MISSING_RESOURCE_ERROR;
1907 }
1908 }
1909}
1910
1911static void
1912initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
1913 field[index].remove();
1914 if (U_SUCCESS(status)) {
1915 UnicodeString pathUString(path.data(), -1, US_INVicu::UnicodeString::kInvariant);
1916 Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
1917 if (leapMonthTable != nullptr) {
1918 UnicodeString leapLabel(false, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar)(int32_t)(sizeof(kLeapTagUChar)/sizeof((kLeapTagUChar)[0])));
1919 UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
1920 if (leapMonthPattern != nullptr) {
1921 field[index].fastCopyFrom(*leapMonthPattern);
1922 } else {
1923 field[index].setToBogus();
1924 }
1925 return;
1926 }
1927 status = U_MISSING_RESOURCE_ERROR;
1928 }
1929}
1930
1931static CharString
1932&buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
1933 return path.clear().append(segment1, -1, errorCode);
1934}
1935
1936static CharString
1937&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1938 UErrorCode &errorCode) {
1939 return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
1940 .append(segment2, -1, errorCode);
1941}
1942
1943static CharString
1944&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1945 const char* segment3, UErrorCode &errorCode) {
1946 return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
1947 .append(segment3, -1, errorCode);
1948}
1949
1950static CharString
1951&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1952 const char* segment3, const char* segment4, UErrorCode &errorCode) {
1953 return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
1954 .append(segment4, -1, errorCode);
1955}
1956
1957typedef struct {
1958 const char * usageTypeName;
1959 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1960} ContextUsageTypeNameToEnumValue;
1961
1962static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1963 // Entries must be sorted by usageTypeName; entry with nullptr name terminates list.
1964 { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1965 { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
1966 { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1967 { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
1968 { "era-name", DateFormatSymbols::kCapContextUsageEraWide },
1969 { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
1970 { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
1971 { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1972 { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1973 { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
1974 { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1975 { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
1976 { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
1977 { nullptr, static_cast<DateFormatSymbols::ECapitalizationContextUsageType>(0) },
1978};
1979
1980// Resource keys to look up localized strings for day periods.
1981// The first one must be midnight and the second must be noon, so that their indices coincide
1982// with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
1983static const char *dayPeriodKeys[] = {"midnight", "noon",
1984 "morning1", "afternoon1", "evening1", "night1",
1985 "morning2", "afternoon2", "evening2", "night2"};
1986
1987UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
1988 int32_t &stringCount, UErrorCode &status) {
1989 if (U_FAILURE(status)) { return nullptr; }
1990
1991 UnicodeString pathUString(path.data(), -1, US_INVicu::UnicodeString::kInvariant);
1992 Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
1993
1994 stringCount = UPRV_LENGTHOF(dayPeriodKeys)(int32_t)(sizeof(dayPeriodKeys)/sizeof((dayPeriodKeys)[0]));
1995 UnicodeString *strings = new UnicodeString[stringCount];
1996 if (strings == nullptr) {
1997 status = U_MEMORY_ALLOCATION_ERROR;
1998 return nullptr;
1999 }
2000
2001 if (map != nullptr) {
2002 for (int32_t i = 0; i < stringCount; ++i) {
2003 UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INVicu::UnicodeString::kInvariant);
2004 UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
2005 if (dayPeriod != nullptr) {
2006 strings[i].fastCopyFrom(*dayPeriod);
2007 } else {
2008 strings[i].setToBogus();
2009 }
2010 }
2011 } else {
2012 for (int32_t i = 0; i < stringCount; i++) {
2013 strings[i].setToBogus();
2014 }
2015 }
2016 return strings;
2017}
2018
2019
2020void
2021DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
2022{
2023 int32_t len = 0;
2024 /* In case something goes wrong, initialize all of the data to nullptr. */
2025 fEras = nullptr;
2026 fErasCount = 0;
2027 fEraNames = nullptr;
2028 fEraNamesCount = 0;
2029 fNarrowEras = nullptr;
2030 fNarrowErasCount = 0;
2031 fMonths = nullptr;
2032 fMonthsCount=0;
2033 fShortMonths = nullptr;
2034 fShortMonthsCount=0;
2035 fNarrowMonths = nullptr;
2036 fNarrowMonthsCount=0;
2037 fStandaloneMonths = nullptr;
2038 fStandaloneMonthsCount=0;
2039 fStandaloneShortMonths = nullptr;
2040 fStandaloneShortMonthsCount=0;
2041 fStandaloneNarrowMonths = nullptr;
2042 fStandaloneNarrowMonthsCount=0;
2043 fWeekdays = nullptr;
2044 fWeekdaysCount=0;
2045 fShortWeekdays = nullptr;
2046 fShortWeekdaysCount=0;
2047 fShorterWeekdays = nullptr;
2048 fShorterWeekdaysCount=0;
2049 fNarrowWeekdays = nullptr;
2050 fNarrowWeekdaysCount=0;
2051 fStandaloneWeekdays = nullptr;
2052 fStandaloneWeekdaysCount=0;
2053 fStandaloneShortWeekdays = nullptr;
2054 fStandaloneShortWeekdaysCount=0;
2055 fStandaloneShorterWeekdays = nullptr;
2056 fStandaloneShorterWeekdaysCount=0;
2057 fStandaloneNarrowWeekdays = nullptr;
2058 fStandaloneNarrowWeekdaysCount=0;
2059 fAmPms = nullptr;
2060 fAmPmsCount=0;
2061 fNarrowAmPms = nullptr;
2062 fNarrowAmPmsCount=0;
2063 fTimeSeparator.setToBogus();
2064 fQuarters = nullptr;
2065 fQuartersCount = 0;
2066 fShortQuarters = nullptr;
2067 fShortQuartersCount = 0;
2068 fNarrowQuarters = nullptr;
2069 fNarrowQuartersCount = 0;
2070 fStandaloneQuarters = nullptr;
2071 fStandaloneQuartersCount = 0;
2072 fStandaloneShortQuarters = nullptr;
2073 fStandaloneShortQuartersCount = 0;
2074 fStandaloneNarrowQuarters = nullptr;
2075 fStandaloneNarrowQuartersCount = 0;
2076 fLeapMonthPatterns = nullptr;
2077 fLeapMonthPatternsCount = 0;
2078 fShortYearNames = nullptr;
2079 fShortYearNamesCount = 0;
2080 fShortZodiacNames = nullptr;
2081 fShortZodiacNamesCount = 0;
2082 fZoneStringsRowCount = 0;
2083 fZoneStringsColCount = 0;
2084 fZoneStrings = nullptr;
2085 fLocaleZoneStrings = nullptr;
2086 fAbbreviatedDayPeriods = nullptr;
2087 fAbbreviatedDayPeriodsCount = 0;
2088 fWideDayPeriods = nullptr;
2089 fWideDayPeriodsCount = 0;
2090 fNarrowDayPeriods = nullptr;
2091 fNarrowDayPeriodsCount = 0;
2092 fStandaloneAbbreviatedDayPeriods = nullptr;
2093 fStandaloneAbbreviatedDayPeriodsCount = 0;
2094 fStandaloneWideDayPeriods = nullptr;
2095 fStandaloneWideDayPeriodsCount = 0;
2096 fStandaloneNarrowDayPeriods = nullptr;
2097 fStandaloneNarrowDayPeriodsCount = 0;
2098 uprv_memset(fCapitalization, 0, sizeof(fCapitalization)):: memset(fCapitalization, 0, sizeof(fCapitalization));
2099
2100 // We need to preserve the requested locale for
2101 // lazy ZoneStringFormat instantiation. ZoneStringFormat
2102 // is region sensitive, thus, bundle locale bundle's locale
2103 // is not sufficient.
2104 fZSFLocale = locale;
2105
2106 if (U_FAILURE(status)) return;
1
Taking false branch
2107
2108 // Create a CalendarDataSink to process this data and the resource bundles
2109 CalendarDataSink calendarSink(status);
2110 LocalUResourceBundlePointer rb(ures_openures_open_77(nullptr, locale.getBaseName(), &status));
2111 LocalUResourceBundlePointer cb(ures_getByKeyures_getByKey_77(rb.getAlias(), gCalendarTag, nullptr, &status));
2112
2113 if (U_FAILURE(status)) return;
2114
2115 // Iterate over the resource bundle data following the fallbacks through different calendar types
2116 UnicodeString calendarType((type != nullptr && *type != '\0')? type : gGregorianTag, -1, US_INVicu::UnicodeString::kInvariant);
2
Assuming the condition is false
2117 while (!calendarType.isBogus()) {
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 2156
2118 CharString calendarTypeBuffer;
2119 calendarTypeBuffer.appendInvariantChars(calendarType, status);
2120 if (U_FAILURE(status)) { return; }
2121 const char *calendarTypeCArray = calendarTypeBuffer.data();
2122
2123 // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2124 UErrorCode oldStatus = status;
2125 LocalUResourceBundlePointer ctb(ures_getByKeyWithFallbackures_getByKeyWithFallback_77(cb.getAlias(), calendarTypeCArray, nullptr, &status));
2126 if (status == U_MISSING_RESOURCE_ERROR) {
2127 if (uprv_strcmp(calendarTypeCArray, gGregorianTag):: strcmp(calendarTypeCArray, gGregorianTag) != 0) {
2128 calendarType.setTo(false, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)(int32_t)(sizeof(kGregorianTagUChar)/sizeof((kGregorianTagUChar
)[0]))
);
2129 calendarSink.visitAllResources();
2130 status = oldStatus;
2131 continue;
2132 }
2133 return;
2134 }
2135
2136 calendarSink.preEnumerate(calendarType);
2137 ures_getAllItemsWithFallbackures_getAllItemsWithFallback_77(ctb.getAlias(), "", calendarSink, status);
2138 if (U_FAILURE(status)) break;
2139
2140 // Stop loading when gregorian was loaded
2141 if (uprv_strcmp(calendarTypeCArray, gGregorianTag):: strcmp(calendarTypeCArray, gGregorianTag) == 0) {
2142 break;
2143 }
2144
2145 // Get the next calendar type to process from the sink
2146 calendarType = calendarSink.nextCalendarType;
2147
2148 // Gregorian is always the last fallback
2149 if (calendarType.isBogus()) {
2150 calendarType.setTo(false, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)(int32_t)(sizeof(kGregorianTagUChar)/sizeof((kGregorianTagUChar
)[0]))
);
2151 calendarSink.visitAllResources();
2152 }
2153 }
2154
2155 // CharString object to build paths
2156 CharString path;
2157
2158 // Load Leap Month Patterns
2159 UErrorCode tempStatus = status;
2160 fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
2161 if (fLeapMonthPatterns) {
5
Assuming field 'fLeapMonthPatterns' is null
6
Taking false branch
2162 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
2163 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
2164 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
2165 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2166 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
2167 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
2168 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
2169 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
2170 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
2171 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
2172 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
2173 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
2174 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
2175 buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
2176 if (U_SUCCESS(tempStatus)) {
2177 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
2178 // The ordering of the following statements is important.
2179 if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
2180 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2181 }
2182 if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
2183 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
2184 }
2185 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
2186 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2187 }
2188 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
2189 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
2190 }
2191 // end of hack
2192 fLeapMonthPatternsCount = kMonthPatternsCount;
2193 } else {
2194 delete[] fLeapMonthPatterns;
2195 fLeapMonthPatterns = nullptr;
2196 }
2197 }
2198
2199 // Load cyclic names sets
2200 tempStatus = status;
2201 initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
2202 buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2203 initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
2204 buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2205
2206 // Load context transforms and capitalization
2207 tempStatus = U_ZERO_ERROR;
2208 LocalUResourceBundlePointer localeBundle(ures_openures_open_77(nullptr, locale.getName(), &tempStatus));
2209 if (U_SUCCESS(tempStatus)) {
7
Taking false branch
2210 LocalUResourceBundlePointer contextTransforms(ures_getByKeyWithFallbackures_getByKeyWithFallback_77(localeBundle.getAlias(), gContextTransformsTag, nullptr, &tempStatus));
2211 if (U_SUCCESS(tempStatus)) {
2212 for (LocalUResourceBundlePointer contextTransformUsage;
2213 contextTransformUsage.adoptInstead(ures_getNextResourceures_getNextResource_77(contextTransforms.getAlias(), nullptr, &tempStatus)),
2214 contextTransformUsage.isValid();) {
2215 const int32_t * intVector = ures_getIntVectorures_getIntVector_77(contextTransformUsage.getAlias(), &len, &status);
2216 if (U_SUCCESS(tempStatus) && intVector != nullptr && len >= 2) {
2217 const char* usageType = ures_getKeyures_getKey_77(contextTransformUsage.getAlias());
2218 if (usageType != nullptr) {
2219 const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
2220 int32_t compResult = 0;
2221 // linear search; list is short and we cannot be sure that bsearch is available
2222 while ( typeMapPtr->usageTypeName != nullptr && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName):: strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
2223 ++typeMapPtr;
2224 }
2225 if (typeMapPtr->usageTypeName != nullptr && compResult == 0) {
2226 fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
2227 fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
2228 }
2229 }
2230 }
2231 tempStatus = U_ZERO_ERROR;
2232 }
2233 }
2234
2235 tempStatus = U_ZERO_ERROR;
2236 const LocalPointer<NumberingSystem> numberingSystem(
2237 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
2238 if (U_SUCCESS(tempStatus)) {
2239 // These functions all fail gracefully if passed nullptr pointers and
2240 // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
2241 // to check for errors once after all calls are made.
2242 const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallbackures_getByKeyWithFallback_77(
2243 localeBundle.getAlias(), gNumberElementsTag, nullptr, &tempStatus));
2244 const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallbackures_getByKeyWithFallback_77(
2245 numberElementsData.getAlias(), numberingSystem->getName(), nullptr, &tempStatus));
2246 const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallbackures_getByKeyWithFallback_77(
2247 nsNameData.getAlias(), gSymbolsTag, nullptr, &tempStatus));
2248 fTimeSeparator = ures_getUnicodeStringByKey(
2249 symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
2250 if (U_FAILURE(tempStatus)) {
2251 fTimeSeparator.setToBogus();
2252 }
2253 }
2254
2255 }
2256
2257 if (fTimeSeparator.isBogus()) {
8
Assuming the condition is false
9
Taking false branch
2258 fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
2259 }
2260
2261 // Load day periods
2262 fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2263 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
2264 fAbbreviatedDayPeriodsCount, status);
2265
2266 fWideDayPeriods = loadDayPeriodStrings(calendarSink,
2267 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
2268 fWideDayPeriodsCount, status);
2269 fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2270 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
2271 fNarrowDayPeriodsCount, status);
2272
2273 fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2274 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
2275 fStandaloneAbbreviatedDayPeriodsCount, status);
2276
2277 fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
2278 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
2279 fStandaloneWideDayPeriodsCount, status);
2280 fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
10
Value assigned to field 'fStandaloneAbbreviatedDayPeriods'
2281 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
2282 fStandaloneNarrowDayPeriodsCount, status);
2283
2284 // Fill in for missing/bogus items (dayPeriods are a map so single items might be missing)
2285 if (U_SUCCESS(status)) {
11
Taking true branch
2286 for (int32_t dpidx = 0; dpidx < fAbbreviatedDayPeriodsCount; ++dpidx) {
12
Assuming 'dpidx' is < field 'fAbbreviatedDayPeriodsCount'
2287 if (dpidx < fWideDayPeriodsCount && fWideDayPeriods != nullptr && fWideDayPeriods[dpidx].isBogus()) {
13
Assuming 'dpidx' is >= field 'fWideDayPeriodsCount'
2288 fWideDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
2289 }
2290 if (dpidx < fNarrowDayPeriodsCount && fNarrowDayPeriods != nullptr && fNarrowDayPeriods[dpidx].isBogus()) {
14
Assuming 'dpidx' is >= field 'fNarrowDayPeriodsCount'
2291 fNarrowDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
2292 }
2293 if (dpidx < fStandaloneAbbreviatedDayPeriodsCount && fStandaloneAbbreviatedDayPeriods != nullptr && fStandaloneAbbreviatedDayPeriods[dpidx].isBogus()) {
15
Assuming 'dpidx' is < field 'fStandaloneAbbreviatedDayPeriodsCount'
16
Assuming pointer value is null
2294 fStandaloneAbbreviatedDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
2295 }
2296 if (dpidx < fStandaloneWideDayPeriodsCount && fStandaloneWideDayPeriods != nullptr && fStandaloneWideDayPeriods[dpidx].isBogus()) {
17
Assuming 'dpidx' is >= field 'fStandaloneWideDayPeriodsCount'
2297 fStandaloneWideDayPeriods[dpidx].fastCopyFrom(fStandaloneAbbreviatedDayPeriods[dpidx]);
2298 }
2299 if (dpidx < fStandaloneNarrowDayPeriodsCount && fStandaloneNarrowDayPeriods != nullptr && fStandaloneNarrowDayPeriods[dpidx].isBogus()) {
18
Assuming 'dpidx' is < field 'fStandaloneNarrowDayPeriodsCount'
19
Assuming the condition is true
20
Assuming the condition is true
21
Taking true branch
2300 fStandaloneNarrowDayPeriods[dpidx].fastCopyFrom(fStandaloneAbbreviatedDayPeriods[dpidx]);
22
Forming reference to null pointer
2301 }
2302 }
2303 }
2304
2305 U_LOCALE_BASED(locBased, *this)LocaleBased locBased((*this).validLocale, (*this).actualLocale
)
;
2306 // if we make it to here, the resource data is cool, and we can get everything out
2307 // of it that we need except for the time-zone and localized-pattern data, which
2308 // are stored in a separate file
2309 locBased.setLocaleIDs(ures_getLocaleByTypeures_getLocaleByType_77(cb.getAlias(), ULOC_VALID_LOCALE, &status),
2310 ures_getLocaleByTypeures_getLocaleByType_77(cb.getAlias(), ULOC_ACTUAL_LOCALE, &status), status);
2311
2312 // Load eras
2313 initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
2314 UErrorCode oldStatus = status;
2315 initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
2316 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2317 status = oldStatus;
2318 assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
2319 }
2320 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
2321 oldStatus = status;
2322 initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
2323 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2324 status = oldStatus;
2325 assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
2326 }
2327
2328 // Load month names
2329 initField(&fMonths, fMonthsCount, calendarSink,
2330 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
2331 initField(&fShortMonths, fShortMonthsCount, calendarSink,
2332 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2333 initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
2334 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2335 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
2336 status = U_ZERO_ERROR;
2337 assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
2338 }
2339 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
2340 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2341 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
2342 status = U_ZERO_ERROR;
2343 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
2344 }
2345
2346 UErrorCode narrowMonthsEC = status;
2347 UErrorCode standaloneNarrowMonthsEC = status;
2348 initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
2349 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
2350 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
2351 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
2352 if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
2353 // If format/narrow not available, use standalone/narrow
2354 assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
2355 } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2356 // If standalone/narrow not available, use format/narrow
2357 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
2358 } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2359 // If neither is available, use format/abbreviated
2360 assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2361 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2362 }
2363
2364 // Load AM/PM markers; if wide or narrow not available, use short
2365 UErrorCode ampmStatus = U_ZERO_ERROR;
2366 initField(&fAmPms, fAmPmsCount, calendarSink,
2367 buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
2368 if (U_FAILURE(ampmStatus)) {
2369 initField(&fAmPms, fAmPmsCount, calendarSink,
2370 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2371 }
2372 ampmStatus = U_ZERO_ERROR;
2373 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2374 buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
2375 if (U_FAILURE(ampmStatus)) {
2376 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2377 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2378 }
2379 if(status == U_MISSING_RESOURCE_ERROR) {
2380 status = U_ZERO_ERROR;
2381 assignArray(fNarrowAmPms, fNarrowAmPmsCount, fAmPms, fAmPmsCount);
2382 }
2383
2384 // Load quarters
2385 initField(&fQuarters, fQuartersCount, calendarSink,
2386 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
2387 initField(&fShortQuarters, fShortQuartersCount, calendarSink,
2388 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2389 if(status == U_MISSING_RESOURCE_ERROR) {
2390 status = U_ZERO_ERROR;
2391 assignArray(fShortQuarters, fShortQuartersCount, fQuarters, fQuartersCount);
2392 }
2393
2394 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
2395 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2396 if(status == U_MISSING_RESOURCE_ERROR) {
2397 status = U_ZERO_ERROR;
2398 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
2399 }
2400 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
2401 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2402 if(status == U_MISSING_RESOURCE_ERROR) {
2403 status = U_ZERO_ERROR;
2404 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
2405 }
2406
2407 // unlike the fields above, narrow format quarters fall back on narrow standalone quarters
2408 initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, calendarSink,
2409 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
2410 initField(&fNarrowQuarters, fNarrowQuartersCount, calendarSink,
2411 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesNarrowTag, status), status);
2412 if(status == U_MISSING_RESOURCE_ERROR) {
2413 status = U_ZERO_ERROR;
2414 assignArray(fNarrowQuarters, fNarrowQuartersCount, fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount);
2415 }
2416
2417 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2418 /*
2419 // fastCopyFrom()/setTo() - see assignArray comments
2420 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2421 fLocalPatternChars.setTo(true, resStr, len);
2422 // If the locale data does not include new pattern chars, use the defaults
2423 // TODO: Consider making this an error, since this may add conflicting characters.
2424 if (len < PATTERN_CHARS_LEN) {
2425 fLocalPatternChars.append(UnicodeString(true, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2426 }
2427 */
2428 fLocalPatternChars.setTo(true, gPatternChars, PATTERN_CHARS_LEN37);
2429
2430 // Format wide weekdays -> fWeekdays
2431 // {sfb} fixed to handle 1-based weekdays
2432 initField(&fWeekdays, fWeekdaysCount, calendarSink,
2433 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
2434
2435 // Format abbreviated weekdays -> fShortWeekdays
2436 initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
2437 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
2438
2439 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2440 initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
2441 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
2442 if (status == U_MISSING_RESOURCE_ERROR) {
2443 status = U_ZERO_ERROR;
2444 assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2445 }
2446
2447 // Stand-alone wide weekdays -> fStandaloneWeekdays
2448 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
2449 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
2450 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
2451 status = U_ZERO_ERROR;
2452 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
2453 }
2454
2455 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2456 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
2457 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
2458 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
2459 status = U_ZERO_ERROR;
2460 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2461 }
2462
2463 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2464 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
2465 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
2466 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
2467 status = U_ZERO_ERROR;
2468 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
2469 }
2470
2471 // Format narrow weekdays -> fNarrowWeekdays
2472 UErrorCode narrowWeeksEC = status;
2473 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
2474 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
2475 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2476 UErrorCode standaloneNarrowWeeksEC = status;
2477 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
2478 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
2479
2480 if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
2481 // If format/narrow not available, use standalone/narrow
2482 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
2483 } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
2484 // If standalone/narrow not available, use format/narrow
2485 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
2486 } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
2487 // If neither is available, use format/abbreviated
2488 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2489 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2490 }
2491
2492 // Last resort fallback in case previous data wasn't loaded
2493 if (U_FAILURE(status))
2494 {
2495 if (useLastResortData)
2496 {
2497 // Handle the case in which there is no resource data present.
2498 // We don't have to generate usable patterns in this situation;
2499 // we just need to produce something that will be semi-intelligible
2500 // in most locales.
2501
2502 status = U_USING_FALLBACK_WARNING;
2503 //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2504 initField(&fEras, fErasCount, reinterpret_cast<const char16_t*>(gLastResortEras), kEraNum, kEraLen, status);
2505 initField(&fEraNames, fEraNamesCount, reinterpret_cast<const char16_t*>(gLastResortEras), kEraNum, kEraLen, status);
2506 initField(&fNarrowEras, fNarrowErasCount, reinterpret_cast<const char16_t*>(gLastResortEras), kEraNum, kEraLen, status);
2507 initField(&fMonths, fMonthsCount, reinterpret_cast<const char16_t*>(gLastResortMonthNames), kMonthNum, kMonthLen, status);
2508 initField(&fShortMonths, fShortMonthsCount, reinterpret_cast<const char16_t*>(gLastResortMonthNames), kMonthNum, kMonthLen, status);
2509 initField(&fNarrowMonths, fNarrowMonthsCount, reinterpret_cast<const char16_t*>(gLastResortMonthNames), kMonthNum, kMonthLen, status);
2510 initField(&fStandaloneMonths, fStandaloneMonthsCount, reinterpret_cast<const char16_t*>(gLastResortMonthNames), kMonthNum, kMonthLen, status);
2511 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, reinterpret_cast<const char16_t*>(gLastResortMonthNames), kMonthNum, kMonthLen, status);
2512 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, reinterpret_cast<const char16_t*>(gLastResortMonthNames), kMonthNum, kMonthLen, status);
2513 initField(&fWeekdays, fWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2514 initField(&fShortWeekdays, fShortWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2515 initField(&fShorterWeekdays, fShorterWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2516 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2517 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2518 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2519 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2520 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, reinterpret_cast<const char16_t*>(gLastResortDayNames), kDayNum, kDayLen, status);
2521 initField(&fAmPms, fAmPmsCount, reinterpret_cast<const char16_t*>(gLastResortAmPmMarkers), kAmPmNum, kAmPmLen, status);
2522 initField(&fNarrowAmPms, fNarrowAmPmsCount, reinterpret_cast<const char16_t*>(gLastResortAmPmMarkers), kAmPmNum, kAmPmLen, status);
2523 initField(&fQuarters, fQuartersCount, reinterpret_cast<const char16_t*>(gLastResortQuarters), kQuarterNum, kQuarterLen, status);
2524 initField(&fShortQuarters, fShortQuartersCount, reinterpret_cast<const char16_t*>(gLastResortQuarters), kQuarterNum, kQuarterLen, status);
2525 initField(&fNarrowQuarters, fNarrowQuartersCount, reinterpret_cast<const char16_t*>(gLastResortQuarters), kQuarterNum, kQuarterLen, status);
2526 initField(&fStandaloneQuarters, fStandaloneQuartersCount, reinterpret_cast<const char16_t*>(gLastResortQuarters), kQuarterNum, kQuarterLen, status);
2527 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, reinterpret_cast<const char16_t*>(gLastResortQuarters), kQuarterNum, kQuarterLen, status);
2528 initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, reinterpret_cast<const char16_t*>(gLastResortQuarters), kQuarterNum, kQuarterLen, status);
2529 fLocalPatternChars.setTo(true, gPatternChars, PATTERN_CHARS_LEN37);
2530 }
2531 }
2532}
2533
2534Locale
2535DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
2536 return LocaleBased::getLocale(validLocale, actualLocale, type, status);
2537}
2538
2539U_NAMESPACE_END}
2540
2541#endif /* #if !UCONFIG_NO_FORMATTING */
2542
2543//eof