Coverage Report

Created: 2026-06-23 06:26

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
9.66k
#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.61k
SharedDateFormatSymbols::~SharedDateFormatSymbols() {
202
8.61k
}
203
204
template<> U_I18N_API
205
const SharedDateFormatSymbols *
206
        LocaleCacheKey<SharedDateFormatSymbols>::createObject(
207
8.85k
                const void * /*unusedContext*/, UErrorCode &status) const {
208
8.85k
    char type[256];
209
8.85k
    Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
210
8.85k
    if (U_FAILURE(status)) {
211
0
        return nullptr;
212
0
    }
213
8.85k
    SharedDateFormatSymbols *shared
214
8.85k
            = new SharedDateFormatSymbols(fLoc, type, status);
215
8.85k
    if (shared == nullptr) {
216
0
        status = U_MEMORY_ALLOCATION_ERROR;
217
0
        return nullptr;
218
0
    }
219
8.85k
    if (U_FAILURE(status)) {
220
89
        delete shared;
221
89
        return nullptr;
222
89
    }
223
8.76k
    shared->addRef();
224
8.76k
    return shared;
225
8.85k
}
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.45M
static inline UnicodeString* newUnicodeStringArray(size_t count) {
272
4.45M
    return new UnicodeString[count ? count : 1];
273
4.45M
}
274
275
//------------------------------------------------------
276
277
DateFormatSymbols * U_EXPORT2
278
DateFormatSymbols::createForLocale(
279
139k
        const Locale& locale, UErrorCode &status) {
280
139k
    const SharedDateFormatSymbols *shared = nullptr;
281
139k
    UnifiedCache::getByLocale(locale, shared, status);
282
139k
    if (U_FAILURE(status)) {
283
555
        return nullptr;
284
555
    }
285
138k
    DateFormatSymbols *result = new DateFormatSymbols(shared->get());
286
138k
    shared->removeRef();
287
138k
    if (result == nullptr) {
288
0
        status = U_MEMORY_ALLOCATION_ERROR;
289
0
        return nullptr;
290
0
    }
291
138k
    return result;
292
138k
}
293
294
DateFormatSymbols::DateFormatSymbols(const Locale& locale,
295
                                     UErrorCode& status)
296
475
    : UObject()
297
475
{
298
475
  initializeData(locale, nullptr,  status);
299
475
}
300
301
DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
302
428
    : UObject()
303
428
{
304
428
  initializeData(Locale::getDefault(), nullptr, status, true);
305
428
}
306
307
308
DateFormatSymbols::DateFormatSymbols(const Locale& locale,
309
                                     const char *type,
310
                                     UErrorCode& status)
311
8.85k
    : UObject()
312
8.85k
{
313
8.85k
  initializeData(locale, type,  status);
314
8.85k
}
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
138k
    : UObject(other)
324
138k
{
325
138k
    copyData(other);
326
138k
}
327
328
void
329
DateFormatSymbols::assignArray(UnicodeString*& dstArray,
330
                               int32_t& dstCount,
331
                               const UnicodeString* srcArray,
332
                               int32_t srcCount)
333
4.44M
{
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.44M
    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.44M
    dstCount = srcCount;
355
4.44M
    dstArray = newUnicodeStringArray(srcCount);
356
4.44M
    if(dstArray != nullptr) {
357
4.44M
        int32_t i;
358
36.6M
        for(i=0; i<srcCount; ++i) {
359
32.1M
            dstArray[i].fastCopyFrom(srcArray[i]);
360
32.1M
        }
361
4.44M
    }
362
4.44M
}
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
138k
DateFormatSymbols::copyData(const DateFormatSymbols& other) {
405
138k
    validLocale = other.validLocale;
406
138k
    actualLocale = other.actualLocale;
407
138k
    assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
408
138k
    assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
409
138k
    assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
410
138k
    assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
411
138k
    assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
412
138k
    assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
413
138k
    assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
414
138k
    assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
415
138k
    assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
416
138k
    assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
417
138k
    assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
418
138k
    assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
419
138k
    assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
420
138k
    assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
421
138k
    assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
422
138k
    assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
423
138k
    assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
424
138k
    assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
425
138k
    assignArray(fWideAmPms, fWideAmPmsCount, other.fWideAmPms, other.fWideAmPmsCount );
426
138k
    assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
427
138k
    fTimeSeparator.fastCopyFrom(other.fTimeSeparator);  // fastCopyFrom() - see assignArray comments
428
138k
    assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
429
138k
    assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
430
138k
    assignArray(fNarrowQuarters, fNarrowQuartersCount, other.fNarrowQuarters, other.fNarrowQuartersCount);
431
138k
    assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
432
138k
    assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
433
138k
    assignArray(fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, other.fStandaloneNarrowQuarters, other.fStandaloneNarrowQuartersCount);
434
138k
    assignArray(fWideDayPeriods, fWideDayPeriodsCount,
435
138k
                other.fWideDayPeriods, other.fWideDayPeriodsCount);
436
138k
    assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
437
138k
                other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
438
138k
    assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
439
138k
                other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
440
138k
    assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
441
138k
                other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
442
138k
    assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
443
138k
                other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
444
138k
    assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
445
138k
                other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
446
138k
    if (other.fLeapMonthPatterns != nullptr) {
447
0
        assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
448
138k
    } else {
449
138k
        fLeapMonthPatterns = nullptr;
450
138k
        fLeapMonthPatternsCount = 0;
451
138k
    }
452
138k
    if (other.fShortYearNames != nullptr) {
453
0
        assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
454
138k
    } else {
455
138k
        fShortYearNames = nullptr;
456
138k
        fShortYearNamesCount = 0;
457
138k
    }
458
138k
    if (other.fShortZodiacNames != nullptr) {
459
0
        assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
460
138k
    } else {
461
138k
        fShortZodiacNames = nullptr;
462
138k
        fShortZodiacNamesCount = 0;
463
138k
    }
464
465
138k
    if (other.fZoneStrings != nullptr) {
466
0
        fZoneStringsColCount = other.fZoneStringsColCount;
467
0
        fZoneStringsRowCount = other.fZoneStringsRowCount;
468
0
        createZoneStrings((const UnicodeString**)other.fZoneStrings);
469
470
138k
    } else {
471
138k
        fZoneStrings = nullptr;
472
138k
        fZoneStringsColCount = 0;
473
138k
        fZoneStringsRowCount = 0;
474
138k
    }
475
138k
    fZSFLocale = other.fZSFLocale;
476
    // Other zone strings data is created on demand
477
138k
    fLocaleZoneStrings = nullptr;
478
479
    // fastCopyFrom() - see assignArray comments
480
138k
    fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
481
482
138k
    uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
483
138k
}
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
148k
{
499
148k
    dispose();
500
148k
}
501
502
void DateFormatSymbols::dispose()
503
148k
{
504
148k
    delete[] fEras;
505
148k
    delete[] fEraNames;
506
148k
    delete[] fNarrowEras;
507
148k
    delete[] fMonths;
508
148k
    delete[] fShortMonths;
509
148k
    delete[] fNarrowMonths;
510
148k
    delete[] fStandaloneMonths;
511
148k
    delete[] fStandaloneShortMonths;
512
148k
    delete[] fStandaloneNarrowMonths;
513
148k
    delete[] fWeekdays;
514
148k
    delete[] fShortWeekdays;
515
148k
    delete[] fShorterWeekdays;
516
148k
    delete[] fNarrowWeekdays;
517
148k
    delete[] fStandaloneWeekdays;
518
148k
    delete[] fStandaloneShortWeekdays;
519
148k
    delete[] fStandaloneShorterWeekdays;
520
148k
    delete[] fStandaloneNarrowWeekdays;
521
148k
    delete[] fAmPms;
522
148k
    delete[] fWideAmPms;
523
148k
    delete[] fNarrowAmPms;
524
148k
    delete[] fQuarters;
525
148k
    delete[] fShortQuarters;
526
148k
    delete[] fNarrowQuarters;
527
148k
    delete[] fStandaloneQuarters;
528
148k
    delete[] fStandaloneShortQuarters;
529
148k
    delete[] fStandaloneNarrowQuarters;
530
148k
    delete[] fLeapMonthPatterns;
531
148k
    delete[] fShortYearNames;
532
148k
    delete[] fShortZodiacNames;
533
148k
    delete[] fAbbreviatedDayPeriods;
534
148k
    delete[] fWideDayPeriods;
535
148k
    delete[] fNarrowDayPeriods;
536
148k
    delete[] fStandaloneAbbreviatedDayPeriods;
537
148k
    delete[] fStandaloneWideDayPeriods;
538
148k
    delete[] fStandaloneNarrowDayPeriods;
539
540
148k
    actualLocale = Locale::getRoot();
541
148k
    validLocale = Locale::getRoot();
542
148k
    disposeZoneStrings();
543
148k
}
544
545
void DateFormatSymbols::disposeZoneStrings()
546
148k
{
547
148k
    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
148k
    if (fLocaleZoneStrings) {
554
303k
        for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
555
303k
            delete[] fLocaleZoneStrings[row];
556
303k
        }
557
475
        uprv_free(fLocaleZoneStrings);
558
475
    }
559
560
148k
    fZoneStrings = nullptr;
561
148k
    fLocaleZoneStrings = nullptr;
562
148k
    fZoneStringsRowCount = 0;
563
148k
    fZoneStringsColCount = 0;
564
148k
}
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
475
{
691
475
    count = fErasCount;
692
475
    return fEras;
693
475
}
694
695
const UnicodeString*
696
DateFormatSymbols::getEraNames(int32_t &count) const
697
475
{
698
475
    count = fEraNamesCount;
699
475
    return fEraNames;
700
475
}
701
702
const UnicodeString*
703
DateFormatSymbols::getNarrowEras(int32_t &count) const
704
475
{
705
475
    count = fNarrowErasCount;
706
475
    return fNarrowEras;
707
475
}
708
709
const UnicodeString*
710
DateFormatSymbols::getMonths(int32_t &count) const
711
475
{
712
475
    count = fMonthsCount;
713
475
    return fMonths;
714
475
}
715
716
const UnicodeString*
717
DateFormatSymbols::getShortMonths(int32_t &count) const
718
475
{
719
475
    count = fShortMonthsCount;
720
475
    return fShortMonths;
721
475
}
722
723
const UnicodeString*
724
DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
725
950
{
726
950
    UnicodeString *returnValue = nullptr;
727
728
950
    switch (context) {
729
385
    case FORMAT :
730
385
        switch(width) {
731
19
        case WIDE :
732
19
            count = fMonthsCount;
733
19
            returnValue = fMonths;
734
19
            break;
735
189
        case ABBREVIATED :
736
220
        case SHORT : // no month data for this, defaults to ABBREVIATED
737
220
            count = fShortMonthsCount;
738
220
            returnValue = fShortMonths;
739
220
            break;
740
25
        case NARROW :
741
25
            count = fNarrowMonthsCount;
742
25
            returnValue = fNarrowMonths;
743
25
            break;
744
0
        case DT_WIDTH_COUNT :
745
0
            break;
746
385
        }
747
385
        break;
748
385
    case STANDALONE :
749
210
        switch(width) {
750
21
        case WIDE :
751
21
            count = fStandaloneMonthsCount;
752
21
            returnValue = fStandaloneMonths;
753
21
            break;
754
67
        case ABBREVIATED :
755
82
        case SHORT : // no month data for this, defaults to ABBREVIATED
756
82
            count = fStandaloneShortMonthsCount;
757
82
            returnValue = fStandaloneShortMonths;
758
82
            break;
759
15
        case NARROW :
760
15
            count = fStandaloneNarrowMonthsCount;
761
15
            returnValue = fStandaloneNarrowMonths;
762
15
            break;
763
1
        case DT_WIDTH_COUNT :
764
1
            break;
765
210
        }
766
210
        break;
767
210
    case DT_CONTEXT_COUNT :
768
1
        break;
769
950
    }
770
950
    return returnValue;
771
950
}
772
773
const UnicodeString*
774
DateFormatSymbols::getWeekdays(int32_t &count) const
775
475
{
776
475
    count = fWeekdaysCount;
777
475
    return fWeekdays;
778
475
}
779
780
const UnicodeString*
781
DateFormatSymbols::getShortWeekdays(int32_t &count) const
782
950
{
783
950
    count = fShortWeekdaysCount;
784
950
    return fShortWeekdays;
785
950
}
786
787
const UnicodeString*
788
DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
789
950
{
790
950
    UnicodeString *returnValue = nullptr;
791
950
    switch (context) {
792
385
    case FORMAT :
793
385
        switch(width) {
794
19
            case WIDE :
795
19
                count = fWeekdaysCount;
796
19
                returnValue = fWeekdays;
797
19
                break;
798
189
            case ABBREVIATED :
799
189
                count = fShortWeekdaysCount;
800
189
                returnValue = fShortWeekdays;
801
189
                break;
802
31
            case SHORT :
803
31
                count = fShorterWeekdaysCount;
804
31
                returnValue = fShorterWeekdays;
805
31
                break;
806
25
            case NARROW :
807
25
                count = fNarrowWeekdaysCount;
808
25
                returnValue = fNarrowWeekdays;
809
25
                break;
810
0
            case DT_WIDTH_COUNT :
811
0
                break;
812
385
        }
813
385
        break;
814
385
    case STANDALONE :
815
210
        switch(width) {
816
21
            case WIDE :
817
21
                count = fStandaloneWeekdaysCount;
818
21
                returnValue = fStandaloneWeekdays;
819
21
                break;
820
67
            case ABBREVIATED :
821
67
                count = fStandaloneShortWeekdaysCount;
822
67
                returnValue = fStandaloneShortWeekdays;
823
67
                break;
824
15
            case SHORT :
825
15
                count = fStandaloneShorterWeekdaysCount;
826
15
                returnValue = fStandaloneShorterWeekdays;
827
15
                break;
828
15
            case NARROW :
829
15
                count = fStandaloneNarrowWeekdaysCount;
830
15
                returnValue = fStandaloneNarrowWeekdays;
831
15
                break;
832
1
            case DT_WIDTH_COUNT :
833
1
                break;
834
210
        }
835
210
        break;
836
210
    case DT_CONTEXT_COUNT :
837
1
        break;
838
950
    }
839
950
    return returnValue;
840
950
}
841
842
const UnicodeString*
843
DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
844
475
{
845
475
    UnicodeString *returnValue = nullptr;
846
847
475
    switch (context) {
848
283
    case FORMAT :
849
283
        switch(width) {
850
19
        case WIDE :
851
19
            count = fQuartersCount;
852
19
            returnValue = fQuarters;
853
19
            break;
854
159
        case ABBREVIATED :
855
190
        case SHORT : // no quarter data for this, defaults to ABBREVIATED
856
190
            count = fShortQuartersCount;
857
190
            returnValue = fShortQuarters;
858
190
            break;
859
25
        case NARROW :
860
25
            count = fNarrowQuartersCount;
861
25
            returnValue = fNarrowQuarters;
862
25
            break;
863
0
        case DT_WIDTH_COUNT :
864
0
            break;
865
283
        }
866
283
        break;
867
283
    case STANDALONE :
868
153
        switch(width) {
869
20
        case WIDE :
870
20
            count = fStandaloneQuartersCount;
871
20
            returnValue = fStandaloneQuarters;
872
20
            break;
873
67
        case ABBREVIATED :
874
82
        case SHORT : // no quarter data for this, defaults to ABBREVIATED
875
82
            count = fStandaloneShortQuartersCount;
876
82
            returnValue = fStandaloneShortQuarters;
877
82
            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
153
        }
885
153
        break;
886
153
    case DT_CONTEXT_COUNT :
887
0
        break;
888
475
    }
889
475
    return returnValue;
890
475
}
891
892
UnicodeString&
893
DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
894
475
{
895
    // fastCopyFrom() - see assignArray comments
896
475
    return result.fastCopyFrom(fTimeSeparator);
897
475
}
898
899
const UnicodeString*
900
DateFormatSymbols::getAmPmStrings(int32_t &count) const
901
475
{
902
475
    return getAmPmStrings(count, FORMAT, ABBREVIATED);
903
475
}
904
905
const UnicodeString*
906
DateFormatSymbols::getAmPmStrings(int32_t &count, DtContextType /*ignored*/, DtWidthType width) const
907
475
{
908
475
    UnicodeString* const* srcArray;
909
475
    int32_t const* srcCount;
910
475
    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
475
    case ABBREVIATED:
920
475
    default:
921
475
        srcArray = &fAmPms;
922
475
        srcCount = &fAmPmsCount;
923
475
        break;
924
475
    }
925
926
475
    count = *srcCount;
927
475
    return *srcArray;
928
475
}
929
930
const UnicodeString*
931
DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
932
475
{
933
475
    count = fLeapMonthPatternsCount;
934
475
    return fLeapMonthPatterns;
935
475
}
936
937
const UnicodeString*
938
DateFormatSymbols::getYearNames(int32_t& count,
939
                                DtContextType /*ignored*/, DtWidthType /*ignored*/) const
940
950
{
941
950
    count = fShortYearNamesCount;
942
950
    return fShortYearNames;
943
950
}
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
950
{
961
950
    count = fShortZodiacNamesCount;
962
950
    return fShortZodiacNames;
963
950
}
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
475
{
1310
475
    const UnicodeString **result = nullptr;
1311
475
    static UMutex LOCK;
1312
1313
475
    umtx_lock(&LOCK);
1314
475
    if (fZoneStrings == nullptr) {
1315
475
        if (fLocaleZoneStrings == nullptr) {
1316
475
            const_cast<DateFormatSymbols*>(this)->initZoneStringsArray();
1317
475
        }
1318
475
        result = (const UnicodeString**)fLocaleZoneStrings;
1319
475
    } else {
1320
0
        result = (const UnicodeString**)fZoneStrings;
1321
0
    }
1322
475
    rowCount = fZoneStringsRowCount;
1323
475
    columnCount = fZoneStringsColCount;
1324
475
    umtx_unlock(&LOCK);
1325
1326
475
    return result;
1327
475
}
1328
1329
// For now, we include all zones
1330
475
#define ZONE_SET UCAL_ZONE_TYPE_ANY
1331
1332
// This code must be called within a synchronized block
1333
void
1334
475
DateFormatSymbols::initZoneStringsArray() {
1335
475
    if (fZoneStrings != nullptr || fLocaleZoneStrings != nullptr) {
1336
0
        return;
1337
0
    }
1338
1339
475
    UErrorCode status = U_ZERO_ERROR;
1340
1341
475
    StringEnumeration *tzids = nullptr;
1342
475
    UnicodeString ** zarray = nullptr;
1343
475
    TimeZoneNames *tzNames = nullptr;
1344
475
    int32_t rows = 0;
1345
1346
475
    static const UTimeZoneNameType TYPES[] = {
1347
475
        UTZNM_LONG_STANDARD, UTZNM_SHORT_STANDARD,
1348
475
        UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_DAYLIGHT
1349
475
    };
1350
475
    static const int32_t NUM_TYPES = 4;
1351
1352
475
    do { // dummy do-while
1353
1354
475
        tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, nullptr, nullptr, status);
1355
475
        rows = tzids->count(status);
1356
475
        if (U_FAILURE(status)) {
1357
0
            break;
1358
0
        }
1359
1360
        // Allocate array
1361
475
        int32_t size = rows * sizeof(UnicodeString*);
1362
475
        zarray = static_cast<UnicodeString**>(uprv_malloc(size));
1363
475
        if (zarray == nullptr) {
1364
0
            status = U_MEMORY_ALLOCATION_ERROR;
1365
0
            break;
1366
0
        }
1367
475
        uprv_memset(zarray, 0, size);
1368
1369
475
        tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1370
475
        tzNames->loadAllDisplayNames(status);
1371
475
        if (U_FAILURE(status)) { break; }
1372
1373
475
        const UnicodeString *tzid;
1374
475
        int32_t i = 0;
1375
475
        UDate now = Calendar::getNow();
1376
475
        UnicodeString tzDispName;
1377
1378
303k
        while ((tzid = tzids->snext(status)) != nullptr) {
1379
303k
            if (U_FAILURE(status)) {
1380
0
                break;
1381
0
            }
1382
1383
303k
            zarray[i] = new UnicodeString[5];
1384
303k
            if (zarray[i] == nullptr) {
1385
0
                status = U_MEMORY_ALLOCATION_ERROR;
1386
0
                break;
1387
0
            }
1388
1389
303k
            zarray[i][0].setTo(*tzid);
1390
303k
            tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
1391
303k
            i++;
1392
303k
        }
1393
1394
475
    } while (false);
1395
1396
475
    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
475
    delete tzNames;
1409
475
    delete tzids;
1410
1411
475
    fLocaleZoneStrings = zarray;
1412
475
    fZoneStringsRowCount = rows;
1413
475
    fZoneStringsColCount = 1 + NUM_TYPES;
1414
475
}
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
252k
DateFormatSymbols::getPatternCharIndex(char16_t c) {
1439
252k
    if (c >= UPRV_LENGTHOF(gLookupPatternChars)) {
1440
0
        return UDAT_FIELD_COUNT;
1441
0
    }
1442
252k
    const auto idx = gLookupPatternChars[c];
1443
252k
    return idx == -1 ? UDAT_FIELD_COUNT : static_cast<UDateFormatField>(idx);
1444
252k
}
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
475
{
1493
    // fastCopyFrom() - see assignArray comments
1494
475
    return result.fastCopyFrom(fLocalPatternChars);
1495
475
}
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
9.75k
    :   arrays(false, status), arraySizes(false, status), maps(false, status),
1580
9.75k
        mapRefs(),
1581
9.75k
        aliasPathPairs(uprv_deleteUObject, uhash_compareUnicodeString, status),
1582
9.75k
        currentCalendarType(), nextCalendarType(),
1583
9.75k
        resourcesToVisit(nullptr), aliasRelativePath() {
1584
9.75k
        if (U_FAILURE(status)) { return; }
1585
9.75k
    }
1586
    virtual ~CalendarDataSink();
1587
1588
    // Configure the CalendarSink to visit all the resources
1589
297
    void visitAllResources() {
1590
297
        resourcesToVisit.adoptInstead(nullptr);
1591
297
    }
1592
1593
    // Actions to be done before enumerating
1594
10.2k
    void preEnumerate(const UnicodeString &calendarType) {
1595
10.2k
        currentCalendarType = calendarType;
1596
10.2k
        nextCalendarType.setToBogus();
1597
10.2k
        aliasPathPairs.removeAllElements();
1598
10.2k
    }
1599
1600
21.5k
    virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) override {
1601
21.5k
        if (U_FAILURE(errorCode)) { return; }
1602
21.5k
        U_ASSERT(!currentCalendarType.isEmpty());
1603
1604
        // Stores the resources to visit on the next calendar.
1605
21.5k
        LocalPointer<UVector> resourcesToVisitNext(nullptr);
1606
21.5k
        ResourceTable calendarData = value.getTable(errorCode);
1607
21.5k
        if (U_FAILURE(errorCode)) { return; }
1608
1609
        // Enumerate all resources for this calendar
1610
275k
        for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
1611
253k
            UnicodeString keyUString(key, -1, US_INV);
1612
1613
            // == Handle aliases ==
1614
253k
            AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
1615
253k
            if (U_FAILURE(errorCode)) { return; }
1616
253k
            if (aliasType == GREGORIAN) {
1617
                // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
1618
3.66k
                continue;
1619
1620
250k
            } 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.24k
                if (resourcesToVisitNext.isNull()) {
1624
302
                    resourcesToVisitNext
1625
302
                        .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, errorCode),
1626
302
                                                       errorCode);
1627
302
                    if (U_FAILURE(errorCode)) { return; }
1628
302
                }
1629
1.24k
                LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1630
1.24k
                resourcesToVisitNext->adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1631
1.24k
                if (U_FAILURE(errorCode)) { return; }
1632
1.24k
                continue;
1633
1634
249k
            } else if (aliasType == SAME_CALENDAR) {
1635
                // Register same-calendar alias
1636
19.3k
                if (arrays.get(aliasRelativePath) == nullptr && maps.get(aliasRelativePath) == nullptr) {
1637
2.62k
                    LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1638
2.62k
                    aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1639
2.62k
                    if (U_FAILURE(errorCode)) { return; }
1640
2.62k
                    LocalPointer<UnicodeString> keyUStringCopy(keyUString.clone(), errorCode);
1641
2.62k
                    aliasPathPairs.adoptElement(keyUStringCopy.orphan(), errorCode);
1642
2.62k
                    if (U_FAILURE(errorCode)) { return; }
1643
2.62k
                }
1644
19.3k
                continue;
1645
19.3k
            }
1646
1647
            // Only visit the resources that were referenced by an alias on the previous calendar
1648
            // (AmPmMarkersAbbr is an exception).
1649
229k
            if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
1650
229k
                && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
1651
1652
            // == Handle data ==
1653
228k
            if (uprv_strcmp(key, gAmPmMarkersTag) == 0
1654
228k
                || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
1655
228k
                || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
1656
29.5k
                if (arrays.get(keyUString) == nullptr) {
1657
20.8k
                    ResourceArray resourceArray = value.getArray(errorCode);
1658
20.8k
                    int32_t arraySize = resourceArray.getSize();
1659
20.8k
                    LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
1660
20.8k
                    value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
1661
20.8k
                    arrays.put(keyUString, stringArray.orphan(), errorCode);
1662
20.8k
                    arraySizes.puti(keyUString, arraySize, errorCode);
1663
20.8k
                    if (U_FAILURE(errorCode)) { return; }
1664
20.8k
                }
1665
198k
            } else if (uprv_strcmp(key, gErasTag) == 0
1666
198k
                       || uprv_strcmp(key, gDayNamesTag) == 0
1667
198k
                       || uprv_strcmp(key, gMonthNamesTag) == 0
1668
198k
                       || uprv_strcmp(key, gQuartersTag) == 0
1669
198k
                       || uprv_strcmp(key, gDayPeriodTag) == 0
1670
198k
                       || uprv_strcmp(key, gMonthPatternsTag) == 0
1671
198k
                       || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
1672
83.8k
                processResource(keyUString, key, value, errorCode);
1673
83.8k
            }
1674
228k
        }
1675
1676
        // Apply same-calendar aliases
1677
21.5k
        UBool modified;
1678
21.5k
        do {
1679
21.5k
            modified = false;
1680
89.0k
            for (int32_t i = 0; i < aliasPathPairs.size();) {
1681
67.4k
                UBool mod = false;
1682
67.4k
                UnicodeString* alias = static_cast<UnicodeString*>(aliasPathPairs[i]);
1683
67.4k
                UnicodeString *aliasArray;
1684
67.4k
                Hashtable *aliasMap;
1685
67.4k
                if ((aliasArray = static_cast<UnicodeString*>(arrays.get(*alias))) != nullptr) {
1686
60.7k
                    UnicodeString* path = static_cast<UnicodeString*>(aliasPathPairs[i + 1]);
1687
60.7k
                    if (arrays.get(*path) == nullptr) {
1688
                        // Clone the array
1689
60.4k
                        int32_t aliasArraySize = arraySizes.geti(*alias);
1690
60.4k
                        LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
1691
60.4k
                        if (U_FAILURE(errorCode)) { return; }
1692
60.4k
                        uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
1693
                        // Put the array on the 'arrays' map
1694
60.4k
                        arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
1695
60.4k
                        arraySizes.puti(*path, aliasArraySize, errorCode);
1696
60.4k
                    }
1697
60.7k
                    if (U_FAILURE(errorCode)) { return; }
1698
60.7k
                    mod = true;
1699
60.7k
                } else if ((aliasMap = static_cast<Hashtable*>(maps.get(*alias))) != nullptr) {
1700
6.72k
                    UnicodeString* path = static_cast<UnicodeString*>(aliasPathPairs[i + 1]);
1701
6.72k
                    if (maps.get(*path) == nullptr) {
1702
6.72k
                        maps.put(*path, aliasMap, errorCode);
1703
6.72k
                    }
1704
6.72k
                    if (U_FAILURE(errorCode)) { return; }
1705
6.72k
                    mod = true;
1706
6.72k
                }
1707
67.4k
                if (mod) {
1708
67.4k
                    aliasPathPairs.removeElementAt(i + 1);
1709
67.4k
                    aliasPathPairs.removeElementAt(i);
1710
67.4k
                    modified = true;
1711
67.4k
                } else {
1712
0
                    i += 2;
1713
0
                }
1714
67.4k
            }
1715
21.5k
        } while (modified && !aliasPathPairs.isEmpty());
1716
1717
        // Set the resources to visit on the next calendar
1718
21.5k
        if (!resourcesToVisitNext.isNull()) {
1719
302
            resourcesToVisit = std::move(resourcesToVisitNext);
1720
302
        }
1721
21.5k
    }
1722
1723
    // Process the nested resource bundle tables
1724
263k
    void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
1725
263k
        if (U_FAILURE(errorCode)) return;
1726
1727
263k
        ResourceTable table = value.getTable(errorCode);
1728
263k
        if (U_FAILURE(errorCode)) return;
1729
263k
        Hashtable* stringMap = nullptr;
1730
1731
        // Iterate over all the elements of the table and add them to the map
1732
1.07M
        for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
1733
811k
            UnicodeString keyUString(key, -1, US_INV);
1734
1735
            // Ignore '%variant' keys
1736
811k
            if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
1737
14.7k
                continue;
1738
14.7k
            }
1739
1740
            // == Handle String elements ==
1741
796k
            if (value.getType() == URES_STRING) {
1742
                // We are on a leaf, store the map elements into the stringMap
1743
263k
                if (i == 0) {
1744
                    // mapRefs will keep ownership of 'stringMap':
1745
57.1k
                    stringMap = mapRefs.create(false, errorCode);
1746
57.1k
                    if (stringMap == nullptr) {
1747
0
                        errorCode = U_MEMORY_ALLOCATION_ERROR;
1748
0
                        return;
1749
0
                    }
1750
57.1k
                    maps.put(path, stringMap, errorCode);
1751
57.1k
                    if (U_FAILURE(errorCode)) { return; }
1752
57.1k
                    stringMap->setValueDeleter(uprv_deleteUObject);
1753
57.1k
                }
1754
263k
                U_ASSERT(stringMap != nullptr);
1755
263k
                int32_t valueStringSize;
1756
263k
                const char16_t *valueString = value.getString(valueStringSize, errorCode);
1757
263k
                if (U_FAILURE(errorCode)) { return; }
1758
263k
                LocalPointer<UnicodeString> valueUString(new UnicodeString(true, valueString, valueStringSize), errorCode);
1759
263k
                stringMap->put(keyUString, valueUString.orphan(), errorCode);
1760
263k
                if (U_FAILURE(errorCode)) { return; }
1761
263k
                continue;
1762
263k
            }
1763
533k
            U_ASSERT(stringMap == nullptr);
1764
1765
            // Store the current path's length and append the current key to the path.
1766
533k
            int32_t pathLength = path.length();
1767
533k
            path.append(SOLIDUS).append(keyUString);
1768
1769
            // In cyclicNameSets ignore everything but years/format/abbreviated
1770
            // and zodiacs/format/abbreviated
1771
533k
            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
533k
            if (arrays.get(path) != nullptr || maps.get(path) != nullptr) {
1800
                // Drop the latest key on the path and continue
1801
153k
                path.retainBetween(0, pathLength);
1802
153k
                continue;
1803
153k
            }
1804
1805
379k
            AliasType aliasType = processAliasFromValue(path, value, errorCode);
1806
379k
            if (U_FAILURE(errorCode)) { return; }
1807
379k
            if (aliasType == SAME_CALENDAR) {
1808
                // Store the alias path and the current path on aliasPathPairs
1809
64.8k
                LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1810
64.8k
                aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1811
64.8k
                if (U_FAILURE(errorCode)) { return; }
1812
64.8k
                LocalPointer<UnicodeString> pathCopy(path.clone(), errorCode);
1813
64.8k
                aliasPathPairs.adoptElement(pathCopy.orphan(), errorCode);
1814
64.8k
                if (U_FAILURE(errorCode)) { return; }
1815
1816
                // Drop the latest key on the path and continue
1817
64.8k
                path.retainBetween(0, pathLength);
1818
64.8k
                continue;
1819
64.8k
            }
1820
315k
            U_ASSERT(aliasType == NONE);
1821
1822
            // == Handle data ==
1823
315k
            if (value.getType() == URES_ARRAY) {
1824
                // We are on a leaf, store the array
1825
135k
                ResourceArray rDataArray = value.getArray(errorCode);
1826
135k
                int32_t dataArraySize = rDataArray.getSize();
1827
135k
                LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
1828
135k
                value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
1829
135k
                arrays.put(path, dataArray.orphan(), errorCode);
1830
135k
                arraySizes.puti(path, dataArraySize, errorCode);
1831
135k
                if (U_FAILURE(errorCode)) { return; }
1832
179k
            } else if (value.getType() == URES_TABLE) {
1833
                // We are not on a leaf, recursively process the subtable.
1834
179k
                processResource(path, key, value, errorCode);
1835
179k
                if (U_FAILURE(errorCode)) { return; }
1836
179k
            }
1837
1838
            // Drop the latest key on the path
1839
315k
            path.retainBetween(0, pathLength);
1840
315k
        }
1841
263k
    }
1842
1843
    // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
1844
    AliasType processAliasFromValue(UnicodeString &currentRelativePath, ResourceValue &value,
1845
633k
                                    UErrorCode &errorCode) {
1846
633k
        if (U_FAILURE(errorCode)) { return NONE; }
1847
1848
633k
        if (value.getType() == URES_ALIAS) {
1849
89.0k
            int32_t aliasPathSize;
1850
89.0k
            const char16_t* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
1851
89.0k
            if (U_FAILURE(errorCode)) { return NONE; }
1852
89.0k
            UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
1853
89.0k
            const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
1854
89.0k
            if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
1855
89.0k
                && aliasPath.length() > aliasPrefixLength) {
1856
89.0k
                int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
1857
89.0k
                if (typeLimit > aliasPrefixLength) {
1858
89.0k
                    const UnicodeString aliasCalendarType =
1859
89.0k
                        aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
1860
89.0k
                    aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
1861
1862
89.0k
                    if (currentCalendarType == aliasCalendarType
1863
84.1k
                        && currentRelativePath != aliasRelativePath) {
1864
                        // If we have an alias to the same calendar, the path to the resource must be different
1865
84.1k
                        return SAME_CALENDAR;
1866
1867
84.1k
                    } else if (currentCalendarType != aliasCalendarType
1868
4.90k
                               && currentRelativePath == aliasRelativePath) {
1869
                        // If we have an alias to a different calendar, the path to the resource must be the same
1870
4.90k
                        if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
1871
3.66k
                            return GREGORIAN;
1872
3.66k
                        } else if (nextCalendarType.isBogus()) {
1873
302
                            nextCalendarType = aliasCalendarType;
1874
302
                            return DIFFERENT_CALENDAR;
1875
946
                        } else if (nextCalendarType == aliasCalendarType) {
1876
946
                            return DIFFERENT_CALENDAR;
1877
946
                        }
1878
4.90k
                    }
1879
89.0k
                }
1880
89.0k
            }
1881
0
            errorCode = U_INTERNAL_PROGRAM_ERROR;
1882
0
            return NONE;
1883
89.0k
        }
1884
544k
        return NONE;
1885
633k
    }
1886
1887
    // Deleter function to be used by 'arrays'
1888
77.3k
    static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
1889
77.3k
        delete[] static_cast<UnicodeString *>(uArray);
1890
77.3k
    }
1891
};
1892
// Virtual destructors have to be defined out of line
1893
9.75k
CalendarDataSink::~CalendarDataSink() {
1894
9.75k
    arrays.setValueDeleter(deleteUnicodeStringArray);
1895
9.75k
}
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
164k
initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
1921
164k
    if (U_SUCCESS(status)) {
1922
154k
        UnicodeString keyUString(key.data(), -1, US_INV);
1923
154k
        UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1924
1925
154k
        if (array != nullptr) {
1926
139k
            length = sink.arraySizes.geti(keyUString);
1927
139k
            *field = array;
1928
            // DateFormatSymbols takes ownership of the array:
1929
139k
            sink.arrays.remove(keyUString);
1930
139k
        } else {
1931
15.5k
            length = 0;
1932
15.5k
            status = U_MISSING_RESOURCE_ERROR;
1933
15.5k
        }
1934
154k
    }
1935
164k
}
1936
1937
static void
1938
77.3k
initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
1939
77.3k
    if (U_SUCCESS(status)) {
1940
77.3k
        UnicodeString keyUString(key.data(), -1, US_INV);
1941
77.3k
        UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1942
1943
77.3k
        if (array != nullptr) {
1944
77.3k
            int32_t arrayLength = sink.arraySizes.geti(keyUString);
1945
77.3k
            length = arrayLength + arrayOffset;
1946
77.3k
            *field = new UnicodeString[length];
1947
77.3k
            if (*field == nullptr) {
1948
0
                status = U_MEMORY_ALLOCATION_ERROR;
1949
0
                return;
1950
0
            }
1951
77.3k
            uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
1952
77.3k
        } else {
1953
0
            length = 0;
1954
0
            status = U_MISSING_RESOURCE_ERROR;
1955
0
        }
1956
77.3k
    }
1957
77.3k
}
1958
1959
static void
1960
28.9k
initEras(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, const UResourceBundle *ctebPtr, const char* eraWidth, int32_t maxEra, UErrorCode &status) {
1961
28.9k
    if (U_SUCCESS(status)) {
1962
28.9k
        length = 0;
1963
28.9k
        UnicodeString keyUString(key.data(), -1, US_INV);
1964
28.9k
        Hashtable *eraNamesTable = static_cast<Hashtable*>(sink.maps.get(keyUString));
1965
1966
28.9k
        if (eraNamesTable != nullptr) {
1967
28.9k
            UErrorCode resStatus = U_ZERO_ERROR;
1968
28.9k
            LocalUResourceBundlePointer ctewb(ures_getByKeyWithFallback(ctebPtr, eraWidth, nullptr, &resStatus));
1969
28.9k
            const UResourceBundle *ctewbPtr = (U_SUCCESS(resStatus))? ctewb.getAlias() : nullptr;
1970
28.9k
            *field = new UnicodeString[maxEra + 1];
1971
28.9k
            if (*field == nullptr) {
1972
0
                status = U_MEMORY_ALLOCATION_ERROR;
1973
0
                return;
1974
0
            }
1975
28.9k
            length = maxEra + 1;
1976
86.1k
            for (int32_t eraCode = 0; eraCode <= maxEra; eraCode++) {
1977
57.1k
                char eraCodeStr[12]; // T_CString_integerToString is documented to generate at most 12 bytes including nul terminator
1978
57.1k
                int32_t eraCodeStrLen = T_CString_integerToString(eraCodeStr, eraCode, 10);
1979
57.1k
                UnicodeString eraCodeKey = UnicodeString(eraCodeStr, eraCodeStrLen, US_INV);
1980
57.1k
                UnicodeString *eraName = static_cast<UnicodeString*>(eraNamesTable->get(eraCodeKey));
1981
57.1k
                (*field)[eraCode].remove();
1982
57.1k
                if (eraName != nullptr) {
1983
                    // Get eraName from map (created by CalendarSink)
1984
56.8k
                    (*field)[eraCode].fastCopyFrom(*eraName);
1985
56.8k
                } else if (ctewbPtr != nullptr) {
1986
                    // Try filling in missing items from parent locale(s)
1987
333
                    resStatus = U_ZERO_ERROR;
1988
333
                    LocalUResourceBundlePointer ctewkb(ures_getByKeyWithFallback(ctewbPtr, eraCodeStr, nullptr, &resStatus));
1989
333
                    if (U_SUCCESS(resStatus)) {
1990
315
                        int32_t eraNameLen;
1991
315
                        const UChar* eraNamePtr = ures_getString(ctewkb.getAlias(), &eraNameLen, &resStatus);
1992
315
                        if (U_SUCCESS(resStatus)) {
1993
315
                            (*field)[eraCode].setTo(false, eraNamePtr, eraNameLen);
1994
315
                        }
1995
315
                    }
1996
333
                }
1997
57.1k
            }
1998
28.9k
            return;
1999
28.9k
        }
2000
0
        status = U_MISSING_RESOURCE_ERROR;
2001
0
    }
2002
28.9k
}
2003
2004
static void
2005
67.6k
initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
2006
67.6k
    field[index].remove();
2007
67.6k
    if (U_SUCCESS(status)) {
2008
9.66k
        UnicodeString pathUString(path.data(), -1, US_INV);
2009
9.66k
        Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
2010
9.66k
        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
9.66k
        status = U_MISSING_RESOURCE_ERROR;
2021
9.66k
    }
2022
67.6k
}
2023
2024
static CharString
2025
396k
&buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
2026
396k
    return path.clear().append(segment1, -1, errorCode);
2027
396k
}
2028
2029
static CharString
2030
&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
2031
367k
                   UErrorCode &errorCode) {
2032
367k
    return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
2033
367k
                                                       .append(segment2, -1, errorCode);
2034
367k
}
2035
2036
static CharString
2037
&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
2038
338k
                   const char* segment3, UErrorCode &errorCode) {
2039
338k
    return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
2040
338k
                                                                 .append(segment3, -1, errorCode);
2041
338k
}
2042
2043
static CharString
2044
&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
2045
19.3k
                   const char* segment3, const char* segment4, UErrorCode &errorCode) {
2046
19.3k
    return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
2047
19.3k
                                                                           .append(segment4, -1, errorCode);
2048
19.3k
}
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
57.9k
                                    int32_t &stringCount,  UErrorCode &status) {
2082
57.9k
    if (U_FAILURE(status)) { return nullptr; }
2083
2084
57.9k
    UnicodeString pathUString(path.data(), -1, US_INV);
2085
57.9k
    Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
2086
2087
57.9k
    stringCount = UPRV_LENGTHOF(dayPeriodKeys);
2088
57.9k
    UnicodeString *strings = new UnicodeString[stringCount];
2089
57.9k
    if (strings == nullptr) {
2090
0
        status = U_MEMORY_ALLOCATION_ERROR;
2091
0
        return nullptr;
2092
0
    }
2093
2094
57.9k
    if (map != nullptr) {
2095
384k
        for (int32_t i = 0; i < stringCount; ++i) {
2096
349k
            UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
2097
349k
            UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
2098
349k
            if (dayPeriod != nullptr) {
2099
189k
                strings[i].fastCopyFrom(*dayPeriod);
2100
189k
            } else {
2101
159k
                strings[i].setToBogus();
2102
159k
            }
2103
349k
        }
2104
34.9k
    } else {
2105
253k
        for (int32_t i = 0; i < stringCount; i++) {
2106
230k
            strings[i].setToBogus();
2107
230k
        }
2108
23.0k
    }
2109
57.9k
    return strings;
2110
57.9k
}
2111
2112
2113
void
2114
DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
2115
9.75k
{
2116
9.75k
    int32_t len = 0;
2117
    /* In case something goes wrong, initialize all of the data to nullptr. */
2118
9.75k
    fEras = nullptr;
2119
9.75k
    fErasCount = 0;
2120
9.75k
    fEraNames = nullptr;
2121
9.75k
    fEraNamesCount = 0;
2122
9.75k
    fNarrowEras = nullptr;
2123
9.75k
    fNarrowErasCount = 0;
2124
9.75k
    fMonths = nullptr;
2125
9.75k
    fMonthsCount=0;
2126
9.75k
    fShortMonths = nullptr;
2127
9.75k
    fShortMonthsCount=0;
2128
9.75k
    fNarrowMonths = nullptr;
2129
9.75k
    fNarrowMonthsCount=0;
2130
9.75k
    fStandaloneMonths = nullptr;
2131
9.75k
    fStandaloneMonthsCount=0;
2132
9.75k
    fStandaloneShortMonths = nullptr;
2133
9.75k
    fStandaloneShortMonthsCount=0;
2134
9.75k
    fStandaloneNarrowMonths = nullptr;
2135
9.75k
    fStandaloneNarrowMonthsCount=0;
2136
9.75k
    fWeekdays = nullptr;
2137
9.75k
    fWeekdaysCount=0;
2138
9.75k
    fShortWeekdays = nullptr;
2139
9.75k
    fShortWeekdaysCount=0;
2140
9.75k
    fShorterWeekdays = nullptr;
2141
9.75k
    fShorterWeekdaysCount=0;
2142
9.75k
    fNarrowWeekdays = nullptr;
2143
9.75k
    fNarrowWeekdaysCount=0;
2144
9.75k
    fStandaloneWeekdays = nullptr;
2145
9.75k
    fStandaloneWeekdaysCount=0;
2146
9.75k
    fStandaloneShortWeekdays = nullptr;
2147
9.75k
    fStandaloneShortWeekdaysCount=0;
2148
9.75k
    fStandaloneShorterWeekdays = nullptr;
2149
9.75k
    fStandaloneShorterWeekdaysCount=0;
2150
9.75k
    fStandaloneNarrowWeekdays = nullptr;
2151
9.75k
    fStandaloneNarrowWeekdaysCount=0;
2152
9.75k
    fAmPms = nullptr;
2153
9.75k
    fAmPmsCount=0;
2154
9.75k
    fWideAmPms = nullptr;
2155
9.75k
    fWideAmPmsCount=0;
2156
9.75k
    fNarrowAmPms = nullptr;
2157
9.75k
    fNarrowAmPmsCount=0;
2158
9.75k
    fTimeSeparator.setToBogus();
2159
9.75k
    fQuarters = nullptr;
2160
9.75k
    fQuartersCount = 0;
2161
9.75k
    fShortQuarters = nullptr;
2162
9.75k
    fShortQuartersCount = 0;
2163
9.75k
    fNarrowQuarters = nullptr;
2164
9.75k
    fNarrowQuartersCount = 0;
2165
9.75k
    fStandaloneQuarters = nullptr;
2166
9.75k
    fStandaloneQuartersCount = 0;
2167
9.75k
    fStandaloneShortQuarters = nullptr;
2168
9.75k
    fStandaloneShortQuartersCount = 0;
2169
9.75k
    fStandaloneNarrowQuarters = nullptr;
2170
9.75k
    fStandaloneNarrowQuartersCount = 0;
2171
9.75k
    fLeapMonthPatterns = nullptr;
2172
9.75k
    fLeapMonthPatternsCount = 0;
2173
9.75k
    fShortYearNames = nullptr;
2174
9.75k
    fShortYearNamesCount = 0;
2175
9.75k
    fShortZodiacNames = nullptr;
2176
9.75k
    fShortZodiacNamesCount = 0;
2177
9.75k
    fZoneStringsRowCount = 0;
2178
9.75k
    fZoneStringsColCount = 0;
2179
9.75k
    fZoneStrings = nullptr;
2180
9.75k
    fLocaleZoneStrings = nullptr;
2181
9.75k
    fAbbreviatedDayPeriods = nullptr;
2182
9.75k
    fAbbreviatedDayPeriodsCount = 0;
2183
9.75k
    fWideDayPeriods = nullptr;
2184
9.75k
    fWideDayPeriodsCount = 0;
2185
9.75k
    fNarrowDayPeriods = nullptr;
2186
9.75k
    fNarrowDayPeriodsCount = 0;
2187
9.75k
    fStandaloneAbbreviatedDayPeriods = nullptr;
2188
9.75k
    fStandaloneAbbreviatedDayPeriodsCount = 0;
2189
9.75k
    fStandaloneWideDayPeriods = nullptr;
2190
9.75k
    fStandaloneWideDayPeriodsCount = 0;
2191
9.75k
    fStandaloneNarrowDayPeriods = nullptr;
2192
9.75k
    fStandaloneNarrowDayPeriodsCount = 0;
2193
9.75k
    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
9.75k
    fZSFLocale = locale;
2200
2201
9.75k
    if (U_FAILURE(status)) return;
2202
2203
    // Create a CalendarDataSink to process this data and the resource bundles
2204
9.75k
    CalendarDataSink calendarSink(status);
2205
9.75k
    LocalUResourceBundlePointer rb(ures_open(nullptr, locale.getBaseName(), &status));
2206
9.75k
    LocalUResourceBundlePointer cb(ures_getByKey(rb.getAlias(), gCalendarTag, nullptr, &status));
2207
2208
9.75k
    if (U_FAILURE(status)) return;
2209
2210
    // Iterate over the resource bundle data following the fallbacks through different calendar types
2211
9.66k
    UnicodeString calendarType((type != nullptr && *type != '\0')? type : gGregorianTag, -1, US_INV);
2212
10.2k
    while (!calendarType.isBogus()) {
2213
10.2k
        CharString calendarTypeBuffer;
2214
10.2k
        calendarTypeBuffer.appendInvariantChars(calendarType, status);
2215
10.2k
        if (U_FAILURE(status)) { return; }
2216
10.2k
        const char *calendarTypeCArray = calendarTypeBuffer.data();
2217
2218
        // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2219
10.2k
        UErrorCode oldStatus = status;
2220
10.2k
        LocalUResourceBundlePointer ctb(ures_getByKeyWithFallback(cb.getAlias(), calendarTypeCArray, nullptr, &status));
2221
10.2k
        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
10.2k
        calendarSink.preEnumerate(calendarType);
2232
10.2k
        ures_getAllItemsWithFallback(ctb.getAlias(), "", calendarSink, status);
2233
10.2k
        if (U_FAILURE(status)) break;
2234
2235
        // Stop loading when gregorian was loaded
2236
10.2k
        if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
2237
9.66k
            break;
2238
9.66k
        }
2239
2240
        // Get the next calendar type to process from the sink
2241
599
        calendarType = calendarSink.nextCalendarType;
2242
2243
        // Gregorian is always the last fallback
2244
599
        if (calendarType.isBogus()) {
2245
297
            calendarType.setTo(false, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2246
297
            calendarSink.visitAllResources();
2247
297
        }
2248
599
    }
2249
2250
    // CharString object to build paths
2251
9.66k
    CharString path;
2252
2253
    // Load Leap Month Patterns
2254
9.66k
    UErrorCode tempStatus = status;
2255
9.66k
    fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
2256
9.66k
    if (fLeapMonthPatterns) {
2257
9.66k
        initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
2258
9.66k
                             buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
2259
9.66k
        initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
2260
9.66k
                             buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2261
9.66k
        initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
2262
9.66k
                             buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
2263
9.66k
        initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
2264
9.66k
                             buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
2265
9.66k
        initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
2266
9.66k
                             buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
2267
9.66k
        initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
2268
9.66k
                             buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
2269
9.66k
        initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
2270
9.66k
                             buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
2271
9.66k
        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
9.66k
        } else {
2289
9.66k
            delete[] fLeapMonthPatterns;
2290
9.66k
            fLeapMonthPatterns = nullptr;
2291
9.66k
        }
2292
9.66k
    }
2293
2294
    // Load cyclic names sets
2295
9.66k
    tempStatus = status;
2296
9.66k
    initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
2297
9.66k
              buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2298
9.66k
    initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
2299
9.66k
              buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2300
2301
    // Load context transforms and capitalization
2302
9.66k
    tempStatus = U_ZERO_ERROR;
2303
9.66k
    LocalUResourceBundlePointer localeBundle(ures_open(nullptr, locale.getName(), &tempStatus));
2304
9.66k
    if (U_SUCCESS(tempStatus)) {
2305
9.66k
        LocalUResourceBundlePointer contextTransforms(ures_getByKeyWithFallback(localeBundle.getAlias(), gContextTransformsTag, nullptr, &tempStatus));
2306
9.66k
        if (U_SUCCESS(tempStatus)) {
2307
5.30k
            for (LocalUResourceBundlePointer contextTransformUsage;
2308
31.2k
                 contextTransformUsage.adoptInstead(ures_getNextResource(contextTransforms.getAlias(), nullptr, &tempStatus)),
2309
31.2k
                 contextTransformUsage.isValid();) {
2310
25.9k
                const int32_t * intVector = ures_getIntVector(contextTransformUsage.getAlias(), &len, &status);
2311
25.9k
                if (U_SUCCESS(tempStatus) && intVector != nullptr && len >= 2) {
2312
25.9k
                    const char* usageType = ures_getKey(contextTransformUsage.getAlias());
2313
25.9k
                    if (usageType != nullptr) {
2314
25.9k
                        const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
2315
25.9k
                        int32_t compResult = 0;
2316
                        // linear search; list is short and we cannot be sure that bsearch is available
2317
223k
                        while ( typeMapPtr->usageTypeName != nullptr && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
2318
197k
                            ++typeMapPtr;
2319
197k
                        }
2320
25.9k
                        if (typeMapPtr->usageTypeName != nullptr && compResult == 0) {
2321
2.30k
                            fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
2322
2.30k
                            fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
2323
2.30k
                        }
2324
25.9k
                    }
2325
25.9k
                }
2326
25.9k
                tempStatus = U_ZERO_ERROR;
2327
25.9k
            }
2328
5.30k
        }
2329
2330
9.66k
        tempStatus = U_ZERO_ERROR;
2331
9.66k
        const LocalPointer<NumberingSystem> numberingSystem(
2332
9.66k
                NumberingSystem::createInstance(locale, tempStatus), tempStatus);
2333
9.66k
        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
9.49k
            const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
2338
9.49k
                    localeBundle.getAlias(), gNumberElementsTag, nullptr, &tempStatus));
2339
9.49k
            const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
2340
9.49k
                    numberElementsData.getAlias(), numberingSystem->getName(), nullptr, &tempStatus));
2341
9.49k
            const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
2342
9.49k
                    nsNameData.getAlias(), gSymbolsTag, nullptr, &tempStatus));
2343
9.49k
            fTimeSeparator = ures_getUnicodeStringByKey(
2344
9.49k
                    symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
2345
9.49k
            if (U_FAILURE(tempStatus)) {
2346
7.02k
                fTimeSeparator.setToBogus();
2347
7.02k
            }
2348
9.49k
        }
2349
2350
9.66k
    }
2351
2352
9.66k
    if (fTimeSeparator.isBogus()) {
2353
7.20k
        fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
2354
7.20k
    }
2355
2356
    // Load day periods
2357
9.66k
    fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2358
9.66k
                            buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
2359
9.66k
                            fAbbreviatedDayPeriodsCount, status);
2360
2361
9.66k
    fWideDayPeriods = loadDayPeriodStrings(calendarSink,
2362
9.66k
                            buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
2363
9.66k
                            fWideDayPeriodsCount, status);
2364
9.66k
    fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2365
9.66k
                            buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
2366
9.66k
                            fNarrowDayPeriodsCount, status);
2367
2368
9.66k
    fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2369
9.66k
                            buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
2370
9.66k
                            fStandaloneAbbreviatedDayPeriodsCount, status);
2371
2372
9.66k
    fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
2373
9.66k
                            buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
2374
9.66k
                            fStandaloneWideDayPeriodsCount, status);
2375
9.66k
    fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2376
9.66k
                            buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
2377
9.66k
                            fStandaloneNarrowDayPeriodsCount, status);
2378
2379
    // Fill in for missing/bogus items (dayPeriods are a map so single items might be missing)
2380
9.66k
    if (U_SUCCESS(status)) {
2381
106k
        for (int32_t dpidx = 0; dpidx < fAbbreviatedDayPeriodsCount; ++dpidx) {
2382
96.6k
            if (dpidx < fWideDayPeriodsCount && fWideDayPeriods != nullptr && fWideDayPeriods[dpidx].isBogus()) {
2383
64.4k
                fWideDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
2384
64.4k
            }
2385
96.6k
            if (dpidx < fNarrowDayPeriodsCount && fNarrowDayPeriods != nullptr && fNarrowDayPeriods[dpidx].isBogus()) {
2386
63.2k
                fNarrowDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
2387
63.2k
            }
2388
96.6k
            if (dpidx < fStandaloneAbbreviatedDayPeriodsCount && fStandaloneAbbreviatedDayPeriods != nullptr && fStandaloneAbbreviatedDayPeriods[dpidx].isBogus()) {
2389
67.4k
                fStandaloneAbbreviatedDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
2390
67.4k
            }
2391
96.6k
            if (dpidx < fStandaloneWideDayPeriodsCount && fStandaloneWideDayPeriods != nullptr && fStandaloneWideDayPeriods[dpidx].isBogus()) {
2392
69.1k
                fStandaloneWideDayPeriods[dpidx].fastCopyFrom(fStandaloneAbbreviatedDayPeriods[dpidx]);
2393
69.1k
            }
2394
96.6k
            if (dpidx < fStandaloneNarrowDayPeriodsCount && fStandaloneNarrowDayPeriods != nullptr && fStandaloneNarrowDayPeriods[dpidx].isBogus()) {
2395
70.1k
                fStandaloneNarrowDayPeriods[dpidx].fastCopyFrom(fStandaloneAbbreviatedDayPeriods[dpidx]);
2396
70.1k
            }
2397
96.6k
        }
2398
9.66k
    }
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
9.66k
    validLocale = Locale(ures_getLocaleByType(cb.getAlias(), ULOC_VALID_LOCALE, &status));
2404
9.66k
    actualLocale = Locale(ures_getLocaleByType(cb.getAlias(), ULOC_ACTUAL_LOCALE, &status));
2405
2406
    // Era setup
2407
9.66k
    if (type == nullptr) {
2408
903
        type = "gregorian";
2409
903
    }
2410
9.66k
    LocalPointer<EraRules> eraRules(EraRules::createInstance(type, false, status));
2411
9.66k
    int32_t maxEra = (U_SUCCESS(status))? eraRules->getMaxEraCode(): 0;
2412
9.66k
    UErrorCode resStatus = U_ZERO_ERROR;
2413
9.66k
    LocalUResourceBundlePointer ctpb(ures_getByKeyWithFallback(cb.getAlias(), type, nullptr, &resStatus));
2414
9.66k
    LocalUResourceBundlePointer cteb(ures_getByKeyWithFallback(ctpb.getAlias(), gErasTag, nullptr, &resStatus));
2415
9.66k
    const UResourceBundle *ctebPtr = (U_SUCCESS(resStatus))? cteb.getAlias() : nullptr;
2416
    // Load eras
2417
9.66k
    initEras(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status),
2418
9.66k
            ctebPtr, gNamesAbbrTag, maxEra, status);
2419
9.66k
    UErrorCode oldStatus = status;
2420
9.66k
    initEras(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status),
2421
9.66k
            ctebPtr, gNamesWideTag, maxEra, status);
2422
9.66k
    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
9.66k
    oldStatus = status;
2428
9.66k
    initEras(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status),
2429
9.66k
            ctebPtr, gNamesNarrowTag, maxEra, status);
2430
9.66k
    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
9.66k
    initField(&fMonths, fMonthsCount, calendarSink,
2437
9.66k
              buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
2438
9.66k
    initField(&fShortMonths, fShortMonthsCount, calendarSink,
2439
9.66k
              buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2440
9.66k
    initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
2441
9.66k
              buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2442
9.66k
    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
9.66k
    initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
2447
9.66k
              buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2448
9.66k
    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
9.66k
    UErrorCode narrowMonthsEC = status;
2454
9.66k
    UErrorCode standaloneNarrowMonthsEC = status;
2455
9.66k
    initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
2456
9.66k
              buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
2457
9.66k
    initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
2458
9.66k
              buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
2459
9.66k
    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
9.66k
    } 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
9.66k
    } 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
9.66k
    ErrorCode ampmStatus;
2473
9.66k
    initField(&fAmPms, fAmPmsCount, calendarSink,
2474
9.66k
              buildResourcePath(path, gAmPmMarkersAbbrTag, ampmStatus), ampmStatus);
2475
9.66k
    if (ampmStatus.isFailure()) {
2476
        // No-op: fall back to last-resort names, which are pre-populated
2477
0
    }
2478
9.66k
    ampmStatus.reset();
2479
9.66k
    initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2480
9.66k
              buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
2481
9.66k
    if (ampmStatus.isFailure()) {
2482
        // Narrow falls back to Abbreviated
2483
4.11k
        assignArray(fNarrowAmPms, fNarrowAmPmsCount, fAmPms, fAmPmsCount);
2484
4.11k
    }
2485
9.66k
    ampmStatus.reset();
2486
9.66k
    initField(&fWideAmPms, fWideAmPmsCount, calendarSink,
2487
9.66k
              buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
2488
9.66k
    if (ampmStatus.isFailure()) {
2489
        // Wide falls back to Abbreviated
2490
1.74k
        assignArray(fWideAmPms, fWideAmPmsCount, fAmPms, fAmPmsCount);
2491
1.74k
    }
2492
9.66k
    ampmStatus.reset();
2493
2494
    // Load quarters
2495
9.66k
    initField(&fQuarters, fQuartersCount, calendarSink,
2496
9.66k
              buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
2497
9.66k
    initField(&fShortQuarters, fShortQuartersCount, calendarSink,
2498
9.66k
              buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2499
9.66k
    if(status == U_MISSING_RESOURCE_ERROR) {
2500
0
        status = U_ZERO_ERROR;
2501
0
        assignArray(fShortQuarters, fShortQuartersCount, fQuarters, fQuartersCount);
2502
0
    }
2503
2504
9.66k
    initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
2505
9.66k
              buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2506
9.66k
    if(status == U_MISSING_RESOURCE_ERROR) {
2507
0
        status = U_ZERO_ERROR;
2508
0
        assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
2509
0
    }
2510
9.66k
    initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
2511
9.66k
              buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2512
9.66k
    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
9.66k
    initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, calendarSink,
2519
9.66k
              buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
2520
9.66k
    initField(&fNarrowQuarters, fNarrowQuartersCount, calendarSink,
2521
9.66k
              buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesNarrowTag, status), status);
2522
9.66k
    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
9.66k
    fLocalPatternChars.setTo(true, gPatternChars, PATTERN_CHARS_LEN);
2539
2540
    // Format wide weekdays -> fWeekdays
2541
    // {sfb} fixed to handle 1-based weekdays
2542
9.66k
    initField(&fWeekdays, fWeekdaysCount, calendarSink,
2543
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
2544
2545
    // Format abbreviated weekdays -> fShortWeekdays
2546
9.66k
    initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
2547
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
2548
2549
    // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2550
9.66k
    initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
2551
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
2552
9.66k
    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
9.66k
    initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
2559
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
2560
9.66k
    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
9.66k
    initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
2567
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
2568
9.66k
    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
9.66k
    initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
2575
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
2576
9.66k
    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
9.66k
    UErrorCode narrowWeeksEC = status;
2583
9.66k
    initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
2584
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
2585
    // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2586
9.66k
    UErrorCode standaloneNarrowWeeksEC = status;
2587
9.66k
    initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
2588
9.66k
              buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
2589
2590
9.66k
    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
9.66k
    } 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
9.66k
    } 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
9.66k
    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
9.66k
}
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