Coverage Report

Created: 2018-09-25 14:53

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