Bug Summary

File:out/../deps/icu-small/source/i18n/dtfmtsym.cpp
Warning:line 256, column 55
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name 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 -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D U_COMMON_IMPLEMENTATION=1 -D U_I18N_IMPLEMENTATION=1 -D U_IO_IMPLEMENTATION=1 -D U_TOOLUTIL_IMPLEMENTATION=1 -D U_ATTRIBUTE_DEPRECATED= -D _CRT_SECURE_NO_DEPRECATE= -D U_STATIC_IMPLEMENTATION=1 -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/icu-small/source/common -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/tools/toolutil -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-deprecated-declarations -Wno-strict-aliasing -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/icu-small/source/i18n/dtfmtsym.cpp

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

../deps/icu-small/source/common/unifiedcache.h

1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4******************************************************************************
5* Copyright (C) 2015, International Business Machines Corporation and
6* others. All Rights Reserved.
7******************************************************************************
8*
9* File UNIFIEDCACHE.H - The ICU Unified cache.
10******************************************************************************
11*/
12
13#ifndef __UNIFIED_CACHE_H__
14#define __UNIFIED_CACHE_H__
15
16#include "utypeinfo.h" // for 'typeid' to work
17
18#include "unicode/uobject.h"
19#include "unicode/locid.h"
20#include "sharedobject.h"
21#include "unicode/unistr.h"
22#include "cstring.h"
23#include "ustr_imp.h"
24
25struct UHashtable;
26struct UHashElement;
27
28U_NAMESPACE_BEGINnamespace icu_71 {
29
30class UnifiedCache;
31
32/**
33 * A base class for all cache keys.
34 */
35class U_COMMON_API CacheKeyBase : public UObject {
36 public:
37 CacheKeyBase() : fCreationStatus(U_ZERO_ERROR), fIsPrimary(false) {}
38
39 /**
40 * Copy constructor. Needed to support cloning.
41 */
42 CacheKeyBase(const CacheKeyBase &other)
43 : UObject(other), fCreationStatus(other.fCreationStatus), fIsPrimary(false) { }
44 virtual ~CacheKeyBase();
45
46 /**
47 * Returns the hash code for this object.
48 */
49 virtual int32_t hashCode() const = 0;
50
51 /**
52 * Clones this object polymorphically. Caller owns returned value.
53 */
54 virtual CacheKeyBase *clone() const = 0;
55
56 /**
57 * Create a new object for this key. Called by cache on cache miss.
58 * createObject must add a reference to the object it returns. Note
59 * that getting an object from the cache and returning it without calling
60 * removeRef on it satisfies this requirement. It can also return NULL
61 * and set status to an error.
62 *
63 * @param creationContext the context in which the object is being
64 * created. May be NULL.
65 * @param status Implementations can return a failure here.
66 * In addition, implementations may return a
67 * non NULL object and set a warning status.
68 */
69 virtual const SharedObject *createObject(
70 const void *creationContext, UErrorCode &status) const = 0;
71
72 /**
73 * Writes a description of this key to buffer and returns buffer. Written
74 * description is NULL terminated.
75 */
76 virtual char *writeDescription(char *buffer, int32_t bufSize) const = 0;
77
78 friend inline bool operator==(const CacheKeyBase& lhs,
79 const CacheKeyBase& rhs) {
80 return lhs.equals(rhs);
81 }
82
83 friend inline bool operator!=(const CacheKeyBase& lhs,
84 const CacheKeyBase& rhs) {
85 return !lhs.equals(rhs);
86 }
87
88 protected:
89 virtual bool equals(const CacheKeyBase& other) const = 0;
90
91 private:
92 mutable UErrorCode fCreationStatus;
93 mutable UBool fIsPrimary;
94 friend class UnifiedCache;
95};
96
97
98
99/**
100 * Templated version of CacheKeyBase.
101 * A key of type LocaleCacheKey<T> maps to a value of type T.
102 */
103template<typename T>
104class CacheKey : public CacheKeyBase {
105 public:
106 virtual ~CacheKey() { }
107 /**
108 * The template parameter, T, determines the hash code returned.
109 */
110 virtual int32_t hashCode() const override {
111 const char *s = typeid(T).name();
112 return ustr_hashCharsNustr_hashCharsN_71(s, static_cast<int32_t>(uprv_strlen(s):: strlen(s)));
113 }
114
115 /**
116 * Use the value type, T, as the description.
117 */
118 virtual char *writeDescription(char *buffer, int32_t bufLen) const override {
119 const char *s = typeid(T).name();
120 uprv_strncpy(buffer, s, bufLen):: strncpy(buffer, s, bufLen);
121 buffer[bufLen - 1] = 0;
122 return buffer;
123 }
124
125 protected:
126 /**
127 * Two objects are equal if they are of the same type.
128 */
129 virtual bool equals(const CacheKeyBase &other) const override {
130 return this == &other || typeid(*this) == typeid(other);
131 }
132};
133
134/**
135 * Cache key based on locale.
136 * A key of type LocaleCacheKey<T> maps to a value of type T.
137 */
138template<typename T>
139class LocaleCacheKey : public CacheKey<T> {
140 protected:
141 Locale fLoc;
142 virtual bool equals(const CacheKeyBase &other) const override {
143 if (!CacheKey<T>::equals(other)) {
144 return false;
145 }
146 // We know this and other are of same class because equals() on
147 // CacheKey returned true.
148 return operator==(static_cast<const LocaleCacheKey<T> &>(other));
149 }
150 public:
151 LocaleCacheKey(const Locale &loc) : fLoc(loc) {}
152 LocaleCacheKey(const LocaleCacheKey<T> &other)
153 : CacheKey<T>(other), fLoc(other.fLoc) { }
154 virtual ~LocaleCacheKey() { }
155 virtual int32_t hashCode() const override {
156 return (int32_t)(37u * (uint32_t)CacheKey<T>::hashCode() + (uint32_t)fLoc.hashCode());
157 }
158 inline bool operator == (const LocaleCacheKey<T> &other) const {
159 return fLoc == other.fLoc;
160 }
161 virtual CacheKeyBase *clone() const override {
162 return new LocaleCacheKey<T>(*this);
163 }
164 virtual const T *createObject(
165 const void *creationContext, UErrorCode &status) const override;
166 /**
167 * Use the locale id as the description.
168 */
169 virtual char *writeDescription(char *buffer, int32_t bufLen) const override {
170 const char *s = fLoc.getName();
171 uprv_strncpy(buffer, s, bufLen):: strncpy(buffer, s, bufLen);
172 buffer[bufLen - 1] = 0;
173 return buffer;
174 }
175
176};
177
178/**
179 * The unified cache. A singleton type.
180 * Design doc here:
181 * https://docs.google.com/document/d/1RwGQJs4N4tawNbf809iYDRCvXoMKqDJihxzYt1ysmd8/edit?usp=sharing
182 */
183class U_COMMON_API UnifiedCache : public UnifiedCacheBase {
184 public:
185 /**
186 * @internal
187 * Do not call directly. Instead use UnifiedCache::getInstance() as
188 * there should be only one UnifiedCache in an application.
189 */
190 UnifiedCache(UErrorCode &status);
191
192 /**
193 * Return a pointer to the global cache instance.
194 */
195 static UnifiedCache *getInstance(UErrorCode &status);
196
197 /**
198 * Fetches a value from the cache by key. Equivalent to
199 * get(key, NULL, ptr, status);
200 */
201 template<typename T>
202 void get(
203 const CacheKey<T>& key,
204 const T *&ptr,
205 UErrorCode &status) const {
206 get(key, NULL__null, ptr, status);
5
Calling 'UnifiedCache::get'
15
Returning from 'UnifiedCache::get'
207 }
16
Returning without writing to 'ptr'
208
209 /**
210 * Fetches value from the cache by key.
211 *
212 * @param key the cache key.
213 * @param creationContext passed verbatim to createObject method of key
214 * @param ptr On entry, ptr must be NULL or be included if
215 * the reference count of the object it points
216 * to. On exit, ptr points to the fetched object
217 * from the cache or is left unchanged on
218 * failure. Caller must call removeRef on ptr
219 * if set to a non NULL value.
220 * @param status Any error returned here. May be set to a
221 * warning value even if ptr is set.
222 */
223 template<typename T>
224 void get(
225 const CacheKey<T>& key,
226 const void *creationContext,
227 const T *&ptr,
228 UErrorCode &status) const {
229 if (U_FAILURE(status)) {
6
Taking false branch
230 return;
231 }
232 UErrorCode creationStatus = U_ZERO_ERROR;
233 const SharedObject *value = NULL__null;
234 _get(key, value, creationContext, creationStatus);
235 const T *tvalue = (const T *) value;
236 if (U_SUCCESS(creationStatus)) {
7
Taking true branch
237 SharedObject::copyPtr(tvalue, ptr);
8
Calling 'SharedObject::copyPtr'
12
Returning from 'SharedObject::copyPtr'
238 }
239 SharedObject::clearPtr(tvalue);
240 // Take care not to overwrite a warning status passed in with
241 // another warning or U_ZERO_ERROR.
242 if (status == U_ZERO_ERROR || U_FAILURE(creationStatus)) {
13
Assuming 'status' is equal to U_ZERO_ERROR
243 status = creationStatus;
244 }
245 }
14
Returning without writing to 'ptr'
246
247#ifdef UNIFIED_CACHE_DEBUG
248 /**
249 * Dumps the contents of this cache to standard error. Used for testing of
250 * cache only.
251 */
252 void dumpContents() const;
253#endif
254
255 /**
256 * Convenience method to get a value of type T from cache for a
257 * particular locale with creationContext == NULL.
258 * @param loc the locale
259 * @param ptr On entry, must be NULL or included in the ref count
260 * of the object to which it points.
261 * On exit, fetched value stored here or is left
262 * unchanged on failure. Caller must call removeRef on
263 * ptr if set to a non NULL value.
264 * @param status Any error returned here. May be set to a
265 * warning value even if ptr is set.
266 */
267 template<typename T>
268 static void getByLocale(
269 const Locale &loc, const T *&ptr, UErrorCode &status) {
270 const UnifiedCache *cache = getInstance(status);
271 if (U_FAILURE(status)) {
3
Taking false branch
272 return;
273 }
274 cache->get(LocaleCacheKey<T>(loc), ptr, status);
4
Calling 'UnifiedCache::get'
17
Returning from 'UnifiedCache::get'
275 }
18
Returning without writing to 'ptr'
276
277#ifdef UNIFIED_CACHE_DEBUG
278 /**
279 * Dumps the cache contents to stderr. For testing only.
280 */
281 static void dump();
282#endif
283
284 /**
285 * Returns the number of keys in this cache. For testing only.
286 */
287 int32_t keyCount() const;
288
289 /**
290 * Removes any values from cache that are not referenced outside
291 * the cache.
292 */
293 void flush() const;
294
295 /**
296 * Configures at what point eviction of unused entries will begin.
297 * Eviction is triggered whenever the number of evictable keys exceeds
298 * BOTH count AND (number of in-use items) * (percentageOfInUseItems / 100).
299 * Once the number of unused entries drops below one of these,
300 * eviction ceases. Because eviction happens incrementally,
301 * the actual unused entry count may exceed both these numbers
302 * from time to time.
303 *
304 * A cache entry is defined as unused if it is not essential to guarantee
305 * that for a given key X, the cache returns the same reference to the
306 * same value as long as the client already holds a reference to that
307 * value.
308 *
309 * If this method is never called, the default settings are 1000 and 100%.
310 *
311 * Although this method is thread-safe, it is designed to be called at
312 * application startup. If it is called in the middle of execution, it
313 * will have no immediate effect on the cache. However over time, the
314 * cache will perform eviction slices in an attempt to honor the new
315 * settings.
316 *
317 * If a client already holds references to many different unique values
318 * in the cache such that the number of those unique values far exceeds
319 * "count" then the cache may not be able to maintain this maximum.
320 * However, if this happens, the cache still guarantees that the number of
321 * unused entries will remain only a small percentage of the total cache
322 * size.
323 *
324 * If the parameters passed are negative, setEvctionPolicy sets status to
325 * U_ILLEGAL_ARGUMENT_ERROR.
326 */
327 void setEvictionPolicy(
328 int32_t count, int32_t percentageOfInUseItems, UErrorCode &status);
329
330
331 /**
332 * Returns how many entries have been auto evicted during the lifetime
333 * of this cache. This only includes auto evicted entries, not
334 * entries evicted because of a call to flush().
335 */
336 int64_t autoEvictedCount() const;
337
338 /**
339 * Returns the unused entry count in this cache. For testing only,
340 * Regular clients will not need this.
341 */
342 int32_t unusedCount() const;
343
344 virtual void handleUnreferencedObject() const override;
345 virtual ~UnifiedCache();
346
347 private:
348 UHashtable *fHashtable;
349 mutable int32_t fEvictPos;
350 mutable int32_t fNumValuesTotal;
351 mutable int32_t fNumValuesInUse;
352 int32_t fMaxUnused;
353 int32_t fMaxPercentageOfInUse;
354 mutable int64_t fAutoEvictedCount;
355 SharedObject *fNoValue;
356
357 UnifiedCache(const UnifiedCache &other);
358 UnifiedCache &operator=(const UnifiedCache &other);
359
360 /**
361 * Flushes the contents of the cache. If cache values hold references to other
362 * cache values then _flush should be called in a loop until it returns false.
363 *
364 * On entry, gCacheMutex must be held.
365 * On exit, those values with are evictable are flushed.
366 *
367 * @param all if false flush evictable items only, which are those with no external
368 * references, plus those that can be safely recreated.<br>
369 * if true, flush all elements. Any values (sharedObjects) with remaining
370 * hard (external) references are not deleted, but are detached from
371 * the cache, so that a subsequent removeRefs can delete them.
372 * _flush is not thread safe when all is true.
373 * @return true if any value in cache was flushed or false otherwise.
374 */
375 UBool _flush(UBool all) const;
376
377 /**
378 * Gets value out of cache.
379 * On entry. gCacheMutex must not be held. value must be NULL. status
380 * must be U_ZERO_ERROR.
381 * On exit. value and status set to what is in cache at key or on cache
382 * miss the key's createObject() is called and value and status are set to
383 * the result of that. In this latter case, best effort is made to add the
384 * value and status to the cache. If createObject() fails to create a value,
385 * fNoValue is stored in cache, and value is set to NULL. Caller must call
386 * removeRef on value if non NULL.
387 */
388 void _get(
389 const CacheKeyBase &key,
390 const SharedObject *&value,
391 const void *creationContext,
392 UErrorCode &status) const;
393
394 /**
395 * Attempts to fetch value and status for key from cache.
396 * On entry, gCacheMutex must not be held value must be NULL and status must
397 * be U_ZERO_ERROR.
398 * On exit, either returns false (In this
399 * case caller should try to create the object) or returns true with value
400 * pointing to the fetched value and status set to fetched status. When
401 * false is returned status may be set to failure if an in progress hash
402 * entry could not be made but value will remain unchanged. When true is
403 * returned, caller must call removeRef() on value.
404 */
405 UBool _poll(
406 const CacheKeyBase &key,
407 const SharedObject *&value,
408 UErrorCode &status) const;
409
410 /**
411 * Places a new value and creationStatus in the cache for the given key.
412 * On entry, gCacheMutex must be held. key must not exist in the cache.
413 * On exit, value and creation status placed under key. Soft reference added
414 * to value on successful add. On error sets status.
415 */
416 void _putNew(
417 const CacheKeyBase &key,
418 const SharedObject *value,
419 const UErrorCode creationStatus,
420 UErrorCode &status) const;
421
422 /**
423 * Places value and status at key if there is no value at key or if cache
424 * entry for key is in progress. Otherwise, it leaves the current value and
425 * status there.
426 *
427 * On entry. gCacheMutex must not be held. Value must be
428 * included in the reference count of the object to which it points.
429 *
430 * On exit, value and status are changed to what was already in the cache if
431 * something was there and not in progress. Otherwise, value and status are left
432 * unchanged in which case they are placed in the cache on a best-effort basis.
433 * Caller must call removeRef() on value.
434 */
435 void _putIfAbsentAndGet(
436 const CacheKeyBase &key,
437 const SharedObject *&value,
438 UErrorCode &status) const;
439
440 /**
441 * Returns the next element in the cache round robin style.
442 * Returns nullptr if the cache is empty.
443 * On entry, gCacheMutex must be held.
444 */
445 const UHashElement *_nextElement() const;
446
447 /**
448 * Return the number of cache items that would need to be evicted
449 * to bring usage into conformance with eviction policy.
450 *
451 * An item corresponds to an entry in the hash table, a hash table element.
452 *
453 * On entry, gCacheMutex must be held.
454 */
455 int32_t _computeCountOfItemsToEvict() const;
456
457 /**
458 * Run an eviction slice.
459 * On entry, gCacheMutex must be held.
460 * _runEvictionSlice runs a slice of the evict pipeline by examining the next
461 * 10 entries in the cache round robin style evicting them if they are eligible.
462 */
463 void _runEvictionSlice() const;
464
465 /**
466 * Register a primary cache entry. A primary key is the first key to create
467 * a given SharedObject value. Subsequent keys whose create function
468 * produce references to an already existing SharedObject are not primary -
469 * they can be evicted and subsequently recreated.
470 *
471 * On entry, gCacheMutex must be held.
472 * On exit, items in use count incremented, entry is marked as a primary
473 * entry, and value registered with cache so that subsequent calls to
474 * addRef() and removeRef() on it correctly interact with the cache.
475 */
476 void _registerPrimary(const CacheKeyBase *theKey, const SharedObject *value) const;
477
478 /**
479 * Store a value and creation error status in given hash entry.
480 * On entry, gCacheMutex must be held. Hash entry element must be in progress.
481 * value must be non NULL.
482 * On Exit, soft reference added to value. value and status stored in hash
483 * entry. Soft reference removed from previous stored value. Waiting
484 * threads notified.
485 */
486 void _put(
487 const UHashElement *element,
488 const SharedObject *value,
489 const UErrorCode status) const;
490 /**
491 * Remove a soft reference, and delete the SharedObject if no references remain.
492 * To be used from within the UnifiedCache implementation only.
493 * gCacheMutex must be held by caller.
494 * @param value the SharedObject to be acted on.
495 */
496 void removeSoftRef(const SharedObject *value) const;
497
498 /**
499 * Increment the hard reference count of the given SharedObject.
500 * gCacheMutex must be held by the caller.
501 * Update numValuesEvictable on transitions between zero and one reference.
502 *
503 * @param value The SharedObject to be referenced.
504 * @return the hard reference count after the addition.
505 */
506 int32_t addHardRef(const SharedObject *value) const;
507
508 /**
509 * Decrement the hard reference count of the given SharedObject.
510 * gCacheMutex must be held by the caller.
511 * Update numValuesEvictable on transitions between one and zero reference.
512 *
513 * @param value The SharedObject to be referenced.
514 * @return the hard reference count after the removal.
515 */
516 int32_t removeHardRef(const SharedObject *value) const;
517
518
519#ifdef UNIFIED_CACHE_DEBUG
520 void _dumpContents() const;
521#endif
522
523 /**
524 * Fetch value and error code from a particular hash entry.
525 * On entry, gCacheMutex must be held. value must be either NULL or must be
526 * included in the ref count of the object to which it points.
527 * On exit, value and status set to what is in the hash entry. Caller must
528 * eventually call removeRef on value.
529 * If hash entry is in progress, value will be set to gNoValue and status will
530 * be set to U_ZERO_ERROR.
531 */
532 void _fetch(const UHashElement *element, const SharedObject *&value,
533 UErrorCode &status) const;
534
535 /**
536 * Determine if given hash entry is in progress.
537 * On entry, gCacheMutex must be held.
538 */
539 UBool _inProgress(const UHashElement *element) const;
540
541 /**
542 * Determine if given hash entry is in progress.
543 * On entry, gCacheMutex must be held.
544 */
545 UBool _inProgress(const SharedObject *theValue, UErrorCode creationStatus) const;
546
547 /**
548 * Determine if given hash entry is eligible for eviction.
549 * On entry, gCacheMutex must be held.
550 */
551 UBool _isEvictable(const UHashElement *element) const;
552};
553
554U_NAMESPACE_END}
555
556#endif

../deps/icu-small/source/common/sharedobject.h

1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4******************************************************************************
5* Copyright (C) 2015-2016, International Business Machines
6* Corporation and others. All Rights Reserved.
7******************************************************************************
8* sharedobject.h
9*/
10
11#ifndef __SHAREDOBJECT_H__
12#define __SHAREDOBJECT_H__
13
14
15#include "unicode/uobject.h"
16#include "umutex.h"
17
18U_NAMESPACE_BEGINnamespace icu_71 {
19
20class SharedObject;
21
22/**
23 * Base class for unified cache exposing enough methods to SharedObject
24 * instances to allow their addRef() and removeRef() methods to
25 * update cache metrics. No other part of ICU, except for SharedObject,
26 * should directly call the methods of this base class.
27 */
28class U_COMMON_API UnifiedCacheBase : public UObject {
29public:
30 UnifiedCacheBase() { }
31
32 /**
33 * Notify the cache implementation that an object was seen transitioning to
34 * zero hard references. The cache may use this to keep track the number of
35 * unreferenced SharedObjects, and to trigger evictions.
36 */
37 virtual void handleUnreferencedObject() const = 0;
38
39 virtual ~UnifiedCacheBase();
40private:
41 UnifiedCacheBase(const UnifiedCacheBase &);
42 UnifiedCacheBase &operator=(const UnifiedCacheBase &);
43};
44
45/**
46 * Base class for shared, reference-counted, auto-deleted objects.
47 * Subclasses can be immutable.
48 * If they are mutable, then they must implement their copy constructor
49 * so that copyOnWrite() works.
50 *
51 * Either stack-allocate, use LocalPointer, or use addRef()/removeRef().
52 * Sharing requires reference-counting.
53 */
54class U_COMMON_API SharedObject : public UObject {
55public:
56 /** Initializes totalRefCount, softRefCount to 0. */
57 SharedObject() :
58 softRefCount(0),
59 hardRefCount(0),
60 cachePtr(NULL__null) {}
61
62 /** Initializes totalRefCount, softRefCount to 0. */
63 SharedObject(const SharedObject &other) :
64 UObject(other),
65 softRefCount(0),
66 hardRefCount(0),
67 cachePtr(NULL__null) {}
68
69 virtual ~SharedObject();
70
71 /**
72 * Increments the number of hard references to this object. Thread-safe.
73 * Not for use from within the Unified Cache implementation.
74 */
75 void addRef() const;
76
77 /**
78 * Decrements the number of hard references to this object, and
79 * arrange for possible cache-eviction and/or deletion if ref
80 * count goes to zero. Thread-safe.
81 *
82 * Not for use from within the UnifiedCache implementation.
83 */
84 void removeRef() const;
85
86 /**
87 * Returns the number of hard references for this object.
88 * Uses a memory barrier.
89 */
90 int32_t getRefCount() const;
91
92 /**
93 * If noHardReferences() == true then this object has no hard references.
94 * Must be called only from within the internals of UnifiedCache.
95 */
96 inline UBool noHardReferences() const { return getRefCount() == 0; }
97
98 /**
99 * If hasHardReferences() == true then this object has hard references.
100 * Must be called only from within the internals of UnifiedCache.
101 */
102 inline UBool hasHardReferences() const { return getRefCount() != 0; }
103
104 /**
105 * Deletes this object if it has no references.
106 * Available for non-cached SharedObjects only. Ownership of cached objects
107 * is with the UnifiedCache, which is solely responsible for eviction and deletion.
108 */
109 void deleteIfZeroRefCount() const;
110
111
112 /**
113 * Returns a writable version of ptr.
114 * If there is exactly one owner, then ptr itself is returned as a
115 * non-const pointer.
116 * If there are multiple owners, then ptr is replaced with a
117 * copy-constructed clone,
118 * and that is returned.
119 * Returns NULL if cloning failed.
120 *
121 * T must be a subclass of SharedObject.
122 */
123 template<typename T>
124 static T *copyOnWrite(const T *&ptr) {
125 const T *p = ptr;
126 if(p->getRefCount() <= 1) { return const_cast<T *>(p); }
127 T *p2 = new T(*p);
128 if(p2 == NULL__null) { return NULL__null; }
129 p->removeRef();
130 ptr = p2;
131 p2->addRef();
132 return p2;
133 }
134
135 /**
136 * Makes dest an owner of the object pointed to by src while adjusting
137 * reference counts and deleting the previous object dest pointed to
138 * if necessary. Before this call is made, dest must either be NULL or
139 * be included in the reference count of the object it points to.
140 *
141 * T must be a subclass of SharedObject.
142 */
143 template<typename T>
144 static void copyPtr(const T *src, const T *&dest) {
145 if(src != dest) {
9
Assuming 'src' is equal to 'dest'
10
Taking false branch
146 if(dest != NULL__null) { dest->removeRef(); }
147 dest = src;
148 if(src != NULL__null) { src->addRef(); }
149 }
150 }
11
Returning without writing to 'dest'
151
152 /**
153 * Equivalent to copyPtr(NULL, dest).
154 */
155 template<typename T>
156 static void clearPtr(const T *&ptr) {
157 if (ptr != NULL__null) {
158 ptr->removeRef();
159 ptr = NULL__null;
160 }
161 }
162
163private:
164 /**
165 * The number of references from the UnifiedCache, which is
166 * the number of times that the sharedObject is stored as a hash table value.
167 * For use by UnifiedCache implementation code only.
168 * All access is synchronized by UnifiedCache's gCacheMutex
169 */
170 mutable int32_t softRefCount;
171 friend class UnifiedCache;
172
173 /**
174 * Reference count, excluding references from within the UnifiedCache implementation.
175 */
176 mutable u_atomic_int32_t hardRefCount;
177
178 mutable const UnifiedCacheBase *cachePtr;
179
180};
181
182U_NAMESPACE_END}
183
184#endif