Coverage Report

Created: 2026-02-05 06:34

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