Coverage Report

Created: 2023-02-22 06:51

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