1/*
2*******************************************************************************
3* Copyright (C) 1997-2014, International Business Machines Corporation and    *
4* others. All Rights Reserved.                                                *
5*******************************************************************************
6*
7* File DTFMTSYM.CPP
8*
9* Modification History:
10*
11*   Date        Name        Description
12*   02/19/97    aliu        Converted from java.
13*   07/21/98    stephen     Added getZoneIndex
14*                            Changed weekdays/short weekdays to be one-based
15*   06/14/99    stephen     Removed SimpleDateFormat::fgTimeZoneDataSuffix
16*   11/16/99    weiv        Added 'Y' and 'e' to fgPatternChars
17*   03/27/00    weiv        Keeping resource bundle around!
18*   06/30/05    emmons      Added eraNames, narrow month/day, standalone context
19*   10/12/05    emmons      Added setters for eraNames, month/day by width/context
20*******************************************************************************
21*/
22#include "unicode/utypes.h"
23
24#if !UCONFIG_NO_FORMATTING
25#include "unicode/ustring.h"
26#include "unicode/dtfmtsym.h"
27#include "unicode/smpdtfmt.h"
28#include "unicode/msgfmt.h"
29#include "unicode/tznames.h"
30#include "cpputils.h"
31#include "ucln_in.h"
32#include "umutex.h"
33#include "cmemory.h"
34#include "cstring.h"
35#include "locbased.h"
36#include "gregoimp.h"
37#include "hash.h"
38#include "uresimp.h"
39#include "ureslocs.h"
40
41// *****************************************************************************
42// class DateFormatSymbols
43// *****************************************************************************
44
45/**
46 * These are static arrays we use only in the case where we have no
47 * resource data.
48 */
49
50#define PATTERN_CHARS_LEN 35
51
52/**
53 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
54 * locales use the same these unlocalized pattern characters.
55 */
56static const UChar gPatternChars[] = {
57    // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr
58    0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
59    0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
60    0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
61    0x55, 0x4F, 0x58, 0x78, 0x72, 0
62};
63
64/* length of an array */
65#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
66
67//------------------------------------------------------
68// Strings of last resort.  These are only used if we have no resource
69// files.  They aren't designed for actual use, just for backup.
70
71// These are the month names and abbreviations of last resort.
72static const UChar gLastResortMonthNames[13][3] =
73{
74    {0x0030, 0x0031, 0x0000}, /* "01" */
75    {0x0030, 0x0032, 0x0000}, /* "02" */
76    {0x0030, 0x0033, 0x0000}, /* "03" */
77    {0x0030, 0x0034, 0x0000}, /* "04" */
78    {0x0030, 0x0035, 0x0000}, /* "05" */
79    {0x0030, 0x0036, 0x0000}, /* "06" */
80    {0x0030, 0x0037, 0x0000}, /* "07" */
81    {0x0030, 0x0038, 0x0000}, /* "08" */
82    {0x0030, 0x0039, 0x0000}, /* "09" */
83    {0x0031, 0x0030, 0x0000}, /* "10" */
84    {0x0031, 0x0031, 0x0000}, /* "11" */
85    {0x0031, 0x0032, 0x0000}, /* "12" */
86    {0x0031, 0x0033, 0x0000}  /* "13" */
87};
88
89// These are the weekday names and abbreviations of last resort.
90static const UChar gLastResortDayNames[8][2] =
91{
92    {0x0030, 0x0000}, /* "0" */
93    {0x0031, 0x0000}, /* "1" */
94    {0x0032, 0x0000}, /* "2" */
95    {0x0033, 0x0000}, /* "3" */
96    {0x0034, 0x0000}, /* "4" */
97    {0x0035, 0x0000}, /* "5" */
98    {0x0036, 0x0000}, /* "6" */
99    {0x0037, 0x0000}  /* "7" */
100};
101
102// These are the quarter names and abbreviations of last resort.
103static const UChar gLastResortQuarters[4][2] =
104{
105    {0x0031, 0x0000}, /* "1" */
106    {0x0032, 0x0000}, /* "2" */
107    {0x0033, 0x0000}, /* "3" */
108    {0x0034, 0x0000}, /* "4" */
109};
110
111// These are the am/pm and BC/AD markers of last resort.
112static const UChar gLastResortAmPmMarkers[2][3] =
113{
114    {0x0041, 0x004D, 0x0000}, /* "AM" */
115    {0x0050, 0x004D, 0x0000}  /* "PM" */
116};
117
118static const UChar gLastResortEras[2][3] =
119{
120    {0x0042, 0x0043, 0x0000}, /* "BC" */
121    {0x0041, 0x0044, 0x0000}  /* "AD" */
122};
123
124/* Sizes for the last resort string arrays */
125typedef enum LastResortSize {
126    kMonthNum = 13,
127    kMonthLen = 3,
128
129    kDayNum = 8,
130    kDayLen = 2,
131
132    kAmPmNum = 2,
133    kAmPmLen = 3,
134
135    kQuarterNum = 4,
136    kQuarterLen = 2,
137
138    kEraNum = 2,
139    kEraLen = 3,
140
141    kZoneNum = 5,
142    kZoneLen = 4,
143
144    kGmtHourNum = 4,
145    kGmtHourLen = 10
146} LastResortSize;
147
148U_NAMESPACE_BEGIN
149
150UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
151
152#define kSUPPLEMENTAL "supplementalData"
153
154/**
155 * These are the tags we expect to see in normal resource bundle files associated
156 * with a locale and calendar
157 */
158static const char gErasTag[]="eras";
159static const char gCyclicNameSetsTag[]="cyclicNameSets";
160static const char gNameSetYearsTag[]="years";
161static const char gNameSetZodiacsTag[]="zodiacs";
162static const char gMonthNamesTag[]="monthNames";
163static const char gMonthPatternsTag[]="monthPatterns";
164static const char gDayNamesTag[]="dayNames";
165static const char gNamesWideTag[]="wide";
166static const char gNamesAbbrTag[]="abbreviated";
167static const char gNamesShortTag[]="short";
168static const char gNamesNarrowTag[]="narrow";
169static const char gNamesAllTag[]="all";
170static const char gNamesLeapTag[]="leap";
171static const char gNamesFormatTag[]="format";
172static const char gNamesStandaloneTag[]="stand-alone";
173static const char gNamesNumericTag[]="numeric";
174static const char gAmPmMarkersTag[]="AmPmMarkers";
175static const char gQuartersTag[]="quarters";
176
177// static const char gZoneStringsTag[]="zoneStrings";
178
179// static const char gLocalPatternCharsTag[]="localPatternChars";
180
181static const char gContextTransformsTag[]="contextTransforms";
182
183static UMutex LOCK = U_MUTEX_INITIALIZER;
184
185/**
186 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
187 * Work around this.
188 */
189static inline UnicodeString* newUnicodeStringArray(size_t count) {
190    return new UnicodeString[count ? count : 1];
191}
192
193//------------------------------------------------------
194
195DateFormatSymbols::DateFormatSymbols(const Locale& locale,
196                                     UErrorCode& status)
197    : UObject()
198{
199  initializeData(locale, NULL,  status);
200}
201
202DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
203    : UObject()
204{
205  initializeData(Locale::getDefault(), NULL, status, TRUE);
206}
207
208
209DateFormatSymbols::DateFormatSymbols(const Locale& locale,
210                                     const char *type,
211                                     UErrorCode& status)
212    : UObject()
213{
214  initializeData(locale, type,  status);
215}
216
217DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
218    : UObject()
219{
220  initializeData(Locale::getDefault(), type, status, TRUE);
221}
222
223DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
224    : UObject(other)
225{
226    copyData(other);
227}
228
229void
230DateFormatSymbols::assignArray(UnicodeString*& dstArray,
231                               int32_t& dstCount,
232                               const UnicodeString* srcArray,
233                               int32_t srcCount)
234{
235    // assignArray() is only called by copyData(), which in turn implements the
236    // copy constructor and the assignment operator.
237    // All strings in a DateFormatSymbols object are created in one of the following
238    // three ways that all allow to safely use UnicodeString::fastCopyFrom():
239    // - readonly-aliases from resource bundles
240    // - readonly-aliases or allocated strings from constants
241    // - safely cloned strings (with owned buffers) from setXYZ() functions
242    //
243    // Note that this is true for as long as DateFormatSymbols can be constructed
244    // only from a locale bundle or set via the cloning API,
245    // *and* for as long as all the strings are in *private* fields, preventing
246    // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
247    dstCount = srcCount;
248    dstArray = newUnicodeStringArray(srcCount);
249    if(dstArray != NULL) {
250        int32_t i;
251        for(i=0; i<srcCount; ++i) {
252            dstArray[i].fastCopyFrom(srcArray[i]);
253        }
254    }
255}
256
257/**
258 * Create a copy, in fZoneStrings, of the given zone strings array.  The
259 * member variables fZoneStringsRowCount and fZoneStringsColCount should
260 * be set already by the caller.
261 */
262void
263DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
264{
265    int32_t row, col;
266    UBool failed = FALSE;
267
268    fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
269    if (fZoneStrings != NULL) {
270        for (row=0; row<fZoneStringsRowCount; ++row)
271        {
272            fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
273            if (fZoneStrings[row] == NULL) {
274                failed = TRUE;
275                break;
276            }
277            for (col=0; col<fZoneStringsColCount; ++col) {
278                // fastCopyFrom() - see assignArray comments
279                fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
280            }
281        }
282    }
283    // If memory allocation failed, roll back and delete fZoneStrings
284    if (failed) {
285        for (int i = row; i >= 0; i--) {
286            delete[] fZoneStrings[i];
287        }
288        uprv_free(fZoneStrings);
289        fZoneStrings = NULL;
290    }
291}
292
293/**
294 * Copy all of the other's data to this.
295 */
296void
297DateFormatSymbols::copyData(const DateFormatSymbols& other) {
298    assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
299    assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
300    assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
301    assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
302    assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
303    assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
304    assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
305    assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
306    assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
307    assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
308    assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
309    assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
310    assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
311    assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
312    assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
313    assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
314    assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
315    assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
316    assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
317    assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
318    assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
319    assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
320    if (other.fLeapMonthPatterns != NULL) {
321        assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
322    } else {
323        fLeapMonthPatterns = NULL;
324        fLeapMonthPatternsCount = 0;
325    }
326    if (other.fShortYearNames != NULL) {
327        assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
328    } else {
329        fShortYearNames = NULL;
330        fShortYearNamesCount = 0;
331    }
332    if (other.fShortZodiacNames != NULL) {
333        assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
334    } else {
335        fShortZodiacNames = NULL;
336        fShortZodiacNamesCount = 0;
337    }
338
339    if (other.fZoneStrings != NULL) {
340        fZoneStringsColCount = other.fZoneStringsColCount;
341        fZoneStringsRowCount = other.fZoneStringsRowCount;
342        createZoneStrings((const UnicodeString**)other.fZoneStrings);
343
344    } else {
345        fZoneStrings = NULL;
346        fZoneStringsColCount = 0;
347        fZoneStringsRowCount = 0;
348    }
349    fZSFLocale = other.fZSFLocale;
350    // Other zone strings data is created on demand
351    fLocaleZoneStrings = NULL;
352
353    // fastCopyFrom() - see assignArray comments
354    fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
355
356    uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
357}
358
359/**
360 * Assignment operator.
361 */
362DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
363{
364    dispose();
365    copyData(other);
366
367    return *this;
368}
369
370DateFormatSymbols::~DateFormatSymbols()
371{
372    dispose();
373}
374
375void DateFormatSymbols::dispose()
376{
377    if (fEras)                      delete[] fEras;
378    if (fEraNames)                  delete[] fEraNames;
379    if (fNarrowEras)                delete[] fNarrowEras;
380    if (fMonths)                    delete[] fMonths;
381    if (fShortMonths)               delete[] fShortMonths;
382    if (fNarrowMonths)              delete[] fNarrowMonths;
383    if (fStandaloneMonths)          delete[] fStandaloneMonths;
384    if (fStandaloneShortMonths)     delete[] fStandaloneShortMonths;
385    if (fStandaloneNarrowMonths)    delete[] fStandaloneNarrowMonths;
386    if (fWeekdays)                  delete[] fWeekdays;
387    if (fShortWeekdays)             delete[] fShortWeekdays;
388    if (fShorterWeekdays)           delete[] fShorterWeekdays;
389    if (fNarrowWeekdays)            delete[] fNarrowWeekdays;
390    if (fStandaloneWeekdays)        delete[] fStandaloneWeekdays;
391    if (fStandaloneShortWeekdays)   delete[] fStandaloneShortWeekdays;
392    if (fStandaloneShorterWeekdays) delete[] fStandaloneShorterWeekdays;
393    if (fStandaloneNarrowWeekdays)  delete[] fStandaloneNarrowWeekdays;
394    if (fAmPms)                     delete[] fAmPms;
395    if (fQuarters)                  delete[] fQuarters;
396    if (fShortQuarters)             delete[] fShortQuarters;
397    if (fStandaloneQuarters)        delete[] fStandaloneQuarters;
398    if (fStandaloneShortQuarters)   delete[] fStandaloneShortQuarters;
399    if (fLeapMonthPatterns)         delete[] fLeapMonthPatterns;
400    if (fShortYearNames)            delete[] fShortYearNames;
401    if (fShortZodiacNames)          delete[] fShortZodiacNames;
402
403    disposeZoneStrings();
404}
405
406void DateFormatSymbols::disposeZoneStrings()
407{
408    if (fZoneStrings) {
409        for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
410            delete[] fZoneStrings[row];
411        }
412        uprv_free(fZoneStrings);
413    }
414    if (fLocaleZoneStrings) {
415        for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
416            delete[] fLocaleZoneStrings[row];
417        }
418        uprv_free(fLocaleZoneStrings);
419    }
420
421    fZoneStrings = NULL;
422    fLocaleZoneStrings = NULL;
423    fZoneStringsRowCount = 0;
424    fZoneStringsColCount = 0;
425}
426
427UBool
428DateFormatSymbols::arrayCompare(const UnicodeString* array1,
429                                const UnicodeString* array2,
430                                int32_t count)
431{
432    if (array1 == array2) return TRUE;
433    while (count>0)
434    {
435        --count;
436        if (array1[count] != array2[count]) return FALSE;
437    }
438    return TRUE;
439}
440
441UBool
442DateFormatSymbols::operator==(const DateFormatSymbols& other) const
443{
444    // First do cheap comparisons
445    if (this == &other) {
446        return TRUE;
447    }
448    if (fErasCount == other.fErasCount &&
449        fEraNamesCount == other.fEraNamesCount &&
450        fNarrowErasCount == other.fNarrowErasCount &&
451        fMonthsCount == other.fMonthsCount &&
452        fShortMonthsCount == other.fShortMonthsCount &&
453        fNarrowMonthsCount == other.fNarrowMonthsCount &&
454        fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
455        fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
456        fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
457        fWeekdaysCount == other.fWeekdaysCount &&
458        fShortWeekdaysCount == other.fShortWeekdaysCount &&
459        fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
460        fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
461        fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
462        fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
463        fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
464        fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
465        fAmPmsCount == other.fAmPmsCount &&
466        fQuartersCount == other.fQuartersCount &&
467        fShortQuartersCount == other.fShortQuartersCount &&
468        fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
469        fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
470        fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
471        fShortYearNamesCount == other.fShortYearNamesCount &&
472        fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
473        (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
474    {
475        // Now compare the arrays themselves
476        if (arrayCompare(fEras, other.fEras, fErasCount) &&
477            arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
478            arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
479            arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
480            arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
481            arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
482            arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
483            arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
484            arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
485            arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
486            arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
487            arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
488            arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
489            arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
490            arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
491            arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
492            arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
493            arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
494            arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
495            arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
496            arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
497            arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
498            arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
499            arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
500            arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount))
501        {
502            // Compare the contents of fZoneStrings
503            if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
504                if (fZSFLocale == other.fZSFLocale) {
505                    return TRUE;
506                }
507            } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
508                if (fZoneStringsRowCount == other.fZoneStringsRowCount
509                    && fZoneStringsColCount == other.fZoneStringsColCount) {
510                    UBool cmpres = TRUE;
511                    for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
512                        cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
513                    }
514                    return cmpres;
515                }
516            }
517            return FALSE;
518        }
519    }
520    return FALSE;
521}
522
523//------------------------------------------------------
524
525const UnicodeString*
526DateFormatSymbols::getEras(int32_t &count) const
527{
528    count = fErasCount;
529    return fEras;
530}
531
532const UnicodeString*
533DateFormatSymbols::getEraNames(int32_t &count) const
534{
535    count = fEraNamesCount;
536    return fEraNames;
537}
538
539const UnicodeString*
540DateFormatSymbols::getNarrowEras(int32_t &count) const
541{
542    count = fNarrowErasCount;
543    return fNarrowEras;
544}
545
546const UnicodeString*
547DateFormatSymbols::getMonths(int32_t &count) const
548{
549    count = fMonthsCount;
550    return fMonths;
551}
552
553const UnicodeString*
554DateFormatSymbols::getShortMonths(int32_t &count) const
555{
556    count = fShortMonthsCount;
557    return fShortMonths;
558}
559
560const UnicodeString*
561DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
562{
563    UnicodeString *returnValue = NULL;
564
565    switch (context) {
566    case FORMAT :
567        switch(width) {
568        case WIDE :
569            count = fMonthsCount;
570            returnValue = fMonths;
571            break;
572        case ABBREVIATED :
573        case SHORT : // no month data for this, defaults to ABBREVIATED
574            count = fShortMonthsCount;
575            returnValue = fShortMonths;
576            break;
577        case NARROW :
578            count = fNarrowMonthsCount;
579            returnValue = fNarrowMonths;
580            break;
581        case DT_WIDTH_COUNT :
582            break;
583        }
584        break;
585    case STANDALONE :
586        switch(width) {
587        case WIDE :
588            count = fStandaloneMonthsCount;
589            returnValue = fStandaloneMonths;
590            break;
591        case ABBREVIATED :
592        case SHORT : // no month data for this, defaults to ABBREVIATED
593            count = fStandaloneShortMonthsCount;
594            returnValue = fStandaloneShortMonths;
595            break;
596        case NARROW :
597            count = fStandaloneNarrowMonthsCount;
598            returnValue = fStandaloneNarrowMonths;
599            break;
600        case DT_WIDTH_COUNT :
601            break;
602        }
603        break;
604    case DT_CONTEXT_COUNT :
605        break;
606    }
607    return returnValue;
608}
609
610const UnicodeString*
611DateFormatSymbols::getWeekdays(int32_t &count) const
612{
613    count = fWeekdaysCount;
614    return fWeekdays;
615}
616
617const UnicodeString*
618DateFormatSymbols::getShortWeekdays(int32_t &count) const
619{
620    count = fShortWeekdaysCount;
621    return fShortWeekdays;
622}
623
624const UnicodeString*
625DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
626{
627    UnicodeString *returnValue = NULL;
628    switch (context) {
629    case FORMAT :
630        switch(width) {
631            case WIDE :
632                count = fWeekdaysCount;
633                returnValue = fWeekdays;
634                break;
635            case ABBREVIATED :
636                count = fShortWeekdaysCount;
637                returnValue = fShortWeekdays;
638                break;
639            case SHORT :
640                count = fShorterWeekdaysCount;
641                returnValue = fShorterWeekdays;
642                break;
643            case NARROW :
644                count = fNarrowWeekdaysCount;
645                returnValue = fNarrowWeekdays;
646                break;
647            case DT_WIDTH_COUNT :
648                break;
649        }
650        break;
651    case STANDALONE :
652        switch(width) {
653            case WIDE :
654                count = fStandaloneWeekdaysCount;
655                returnValue = fStandaloneWeekdays;
656                break;
657            case ABBREVIATED :
658                count = fStandaloneShortWeekdaysCount;
659                returnValue = fStandaloneShortWeekdays;
660                break;
661            case SHORT :
662                count = fStandaloneShorterWeekdaysCount;
663                returnValue = fStandaloneShorterWeekdays;
664                break;
665            case NARROW :
666                count = fStandaloneNarrowWeekdaysCount;
667                returnValue = fStandaloneNarrowWeekdays;
668                break;
669            case DT_WIDTH_COUNT :
670                break;
671        }
672        break;
673    case DT_CONTEXT_COUNT :
674        break;
675    }
676    return returnValue;
677}
678
679const UnicodeString*
680DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
681{
682    UnicodeString *returnValue = NULL;
683
684    switch (context) {
685    case FORMAT :
686        switch(width) {
687        case WIDE :
688            count = fQuartersCount;
689            returnValue = fQuarters;
690            break;
691        case ABBREVIATED :
692        case SHORT : // no quarter data for this, defaults to ABBREVIATED
693            count = fShortQuartersCount;
694            returnValue = fShortQuarters;
695            break;
696        case NARROW :
697            count = 0;
698            returnValue = NULL;
699            break;
700        case DT_WIDTH_COUNT :
701            break;
702        }
703        break;
704    case STANDALONE :
705        switch(width) {
706        case WIDE :
707            count = fStandaloneQuartersCount;
708            returnValue = fStandaloneQuarters;
709            break;
710        case ABBREVIATED :
711        case SHORT : // no quarter data for this, defaults to ABBREVIATED
712            count = fStandaloneShortQuartersCount;
713            returnValue = fStandaloneShortQuarters;
714            break;
715        case NARROW :
716            count = 0;
717            returnValue = NULL;
718            break;
719        case DT_WIDTH_COUNT :
720            break;
721        }
722        break;
723    case DT_CONTEXT_COUNT :
724        break;
725    }
726    return returnValue;
727}
728
729const UnicodeString*
730DateFormatSymbols::getAmPmStrings(int32_t &count) const
731{
732    count = fAmPmsCount;
733    return fAmPms;
734}
735
736const UnicodeString*
737DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
738{
739    count = fLeapMonthPatternsCount;
740    return fLeapMonthPatterns;
741}
742
743const UnicodeString*
744DateFormatSymbols::getZodiacNames(int32_t &count) const
745{
746    count = fShortZodiacNamesCount;
747    return fShortZodiacNames;
748}
749
750//------------------------------------------------------
751
752void
753DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
754{
755    // delete the old list if we own it
756    if (fEras)
757        delete[] fEras;
758
759    // we always own the new list, which we create here (we duplicate rather
760    // than adopting the list passed in)
761    fEras = newUnicodeStringArray(count);
762    uprv_arrayCopy(erasArray,fEras,  count);
763    fErasCount = count;
764}
765
766void
767DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
768{
769    // delete the old list if we own it
770    if (fEraNames)
771        delete[] fEraNames;
772
773    // we always own the new list, which we create here (we duplicate rather
774    // than adopting the list passed in)
775    fEraNames = newUnicodeStringArray(count);
776    uprv_arrayCopy(eraNamesArray,fEraNames,  count);
777    fEraNamesCount = count;
778}
779
780void
781DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
782{
783    // delete the old list if we own it
784    if (fNarrowEras)
785        delete[] fNarrowEras;
786
787    // we always own the new list, which we create here (we duplicate rather
788    // than adopting the list passed in)
789    fNarrowEras = newUnicodeStringArray(count);
790    uprv_arrayCopy(narrowErasArray,fNarrowEras,  count);
791    fNarrowErasCount = count;
792}
793
794void
795DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
796{
797    // delete the old list if we own it
798    if (fMonths)
799        delete[] fMonths;
800
801    // we always own the new list, which we create here (we duplicate rather
802    // than adopting the list passed in)
803    fMonths = newUnicodeStringArray(count);
804    uprv_arrayCopy( monthsArray,fMonths,count);
805    fMonthsCount = count;
806}
807
808void
809DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
810{
811    // delete the old list if we own it
812    if (fShortMonths)
813        delete[] fShortMonths;
814
815    // we always own the new list, which we create here (we duplicate rather
816    // than adopting the list passed in)
817    fShortMonths = newUnicodeStringArray(count);
818    uprv_arrayCopy(shortMonthsArray,fShortMonths,  count);
819    fShortMonthsCount = count;
820}
821
822void
823DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
824{
825    // delete the old list if we own it
826    // we always own the new list, which we create here (we duplicate rather
827    // than adopting the list passed in)
828
829    switch (context) {
830    case FORMAT :
831        switch (width) {
832        case WIDE :
833            if (fMonths)
834                delete[] fMonths;
835            fMonths = newUnicodeStringArray(count);
836            uprv_arrayCopy( monthsArray,fMonths,count);
837            fMonthsCount = count;
838            break;
839        case ABBREVIATED :
840            if (fShortMonths)
841                delete[] fShortMonths;
842            fShortMonths = newUnicodeStringArray(count);
843            uprv_arrayCopy( monthsArray,fShortMonths,count);
844            fShortMonthsCount = count;
845            break;
846        case NARROW :
847            if (fNarrowMonths)
848                delete[] fNarrowMonths;
849            fNarrowMonths = newUnicodeStringArray(count);
850            uprv_arrayCopy( monthsArray,fNarrowMonths,count);
851            fNarrowMonthsCount = count;
852            break;
853        default :
854            break;
855        }
856        break;
857    case STANDALONE :
858        switch (width) {
859        case WIDE :
860            if (fStandaloneMonths)
861                delete[] fStandaloneMonths;
862            fStandaloneMonths = newUnicodeStringArray(count);
863            uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
864            fStandaloneMonthsCount = count;
865            break;
866        case ABBREVIATED :
867            if (fStandaloneShortMonths)
868                delete[] fStandaloneShortMonths;
869            fStandaloneShortMonths = newUnicodeStringArray(count);
870            uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
871            fStandaloneShortMonthsCount = count;
872            break;
873        case NARROW :
874           if (fStandaloneNarrowMonths)
875                delete[] fStandaloneNarrowMonths;
876            fStandaloneNarrowMonths = newUnicodeStringArray(count);
877            uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
878            fStandaloneNarrowMonthsCount = count;
879            break;
880        default :
881            break;
882        }
883        break;
884    case DT_CONTEXT_COUNT :
885        break;
886    }
887}
888
889void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
890{
891    // delete the old list if we own it
892    if (fWeekdays)
893        delete[] fWeekdays;
894
895    // we always own the new list, which we create here (we duplicate rather
896    // than adopting the list passed in)
897    fWeekdays = newUnicodeStringArray(count);
898    uprv_arrayCopy(weekdaysArray,fWeekdays,count);
899    fWeekdaysCount = count;
900}
901
902void
903DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
904{
905    // delete the old list if we own it
906    if (fShortWeekdays)
907        delete[] fShortWeekdays;
908
909    // we always own the new list, which we create here (we duplicate rather
910    // than adopting the list passed in)
911    fShortWeekdays = newUnicodeStringArray(count);
912    uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
913    fShortWeekdaysCount = count;
914}
915
916void
917DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
918{
919    // delete the old list if we own it
920    // we always own the new list, which we create here (we duplicate rather
921    // than adopting the list passed in)
922
923    switch (context) {
924    case FORMAT :
925        switch (width) {
926        case WIDE :
927            if (fWeekdays)
928                delete[] fWeekdays;
929            fWeekdays = newUnicodeStringArray(count);
930            uprv_arrayCopy(weekdaysArray, fWeekdays, count);
931            fWeekdaysCount = count;
932            break;
933        case ABBREVIATED :
934            if (fShortWeekdays)
935                delete[] fShortWeekdays;
936            fShortWeekdays = newUnicodeStringArray(count);
937            uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
938            fShortWeekdaysCount = count;
939            break;
940        case SHORT :
941            if (fShorterWeekdays)
942                delete[] fShorterWeekdays;
943            fShorterWeekdays = newUnicodeStringArray(count);
944            uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
945            fShorterWeekdaysCount = count;
946            break;
947        case NARROW :
948            if (fNarrowWeekdays)
949                delete[] fNarrowWeekdays;
950            fNarrowWeekdays = newUnicodeStringArray(count);
951            uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
952            fNarrowWeekdaysCount = count;
953            break;
954        case DT_WIDTH_COUNT :
955            break;
956        }
957        break;
958    case STANDALONE :
959        switch (width) {
960        case WIDE :
961            if (fStandaloneWeekdays)
962                delete[] fStandaloneWeekdays;
963            fStandaloneWeekdays = newUnicodeStringArray(count);
964            uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
965            fStandaloneWeekdaysCount = count;
966            break;
967        case ABBREVIATED :
968            if (fStandaloneShortWeekdays)
969                delete[] fStandaloneShortWeekdays;
970            fStandaloneShortWeekdays = newUnicodeStringArray(count);
971            uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
972            fStandaloneShortWeekdaysCount = count;
973            break;
974        case SHORT :
975            if (fStandaloneShorterWeekdays)
976                delete[] fStandaloneShorterWeekdays;
977            fStandaloneShorterWeekdays = newUnicodeStringArray(count);
978            uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
979            fStandaloneShorterWeekdaysCount = count;
980            break;
981        case NARROW :
982            if (fStandaloneNarrowWeekdays)
983                delete[] fStandaloneNarrowWeekdays;
984            fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
985            uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
986            fStandaloneNarrowWeekdaysCount = count;
987            break;
988        case DT_WIDTH_COUNT :
989            break;
990        }
991        break;
992    case DT_CONTEXT_COUNT :
993        break;
994    }
995}
996
997void
998DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
999{
1000    // delete the old list if we own it
1001    // we always own the new list, which we create here (we duplicate rather
1002    // than adopting the list passed in)
1003
1004    switch (context) {
1005    case FORMAT :
1006        switch (width) {
1007        case WIDE :
1008            if (fQuarters)
1009                delete[] fQuarters;
1010            fQuarters = newUnicodeStringArray(count);
1011            uprv_arrayCopy( quartersArray,fQuarters,count);
1012            fQuartersCount = count;
1013            break;
1014        case ABBREVIATED :
1015            if (fShortQuarters)
1016                delete[] fShortQuarters;
1017            fShortQuarters = newUnicodeStringArray(count);
1018            uprv_arrayCopy( quartersArray,fShortQuarters,count);
1019            fShortQuartersCount = count;
1020            break;
1021        case NARROW :
1022        /*
1023            if (fNarrowQuarters)
1024                delete[] fNarrowQuarters;
1025            fNarrowQuarters = newUnicodeStringArray(count);
1026            uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1027            fNarrowQuartersCount = count;
1028        */
1029            break;
1030        default :
1031            break;
1032        }
1033        break;
1034    case STANDALONE :
1035        switch (width) {
1036        case WIDE :
1037            if (fStandaloneQuarters)
1038                delete[] fStandaloneQuarters;
1039            fStandaloneQuarters = newUnicodeStringArray(count);
1040            uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
1041            fStandaloneQuartersCount = count;
1042            break;
1043        case ABBREVIATED :
1044            if (fStandaloneShortQuarters)
1045                delete[] fStandaloneShortQuarters;
1046            fStandaloneShortQuarters = newUnicodeStringArray(count);
1047            uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
1048            fStandaloneShortQuartersCount = count;
1049            break;
1050        case NARROW :
1051        /*
1052           if (fStandaloneNarrowQuarters)
1053                delete[] fStandaloneNarrowQuarters;
1054            fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1055            uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1056            fStandaloneNarrowQuartersCount = count;
1057        */
1058            break;
1059        default :
1060            break;
1061        }
1062        break;
1063    case DT_CONTEXT_COUNT :
1064        break;
1065    }
1066}
1067
1068void
1069DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
1070{
1071    // delete the old list if we own it
1072    if (fAmPms) delete[] fAmPms;
1073
1074    // we always own the new list, which we create here (we duplicate rather
1075    // than adopting the list passed in)
1076    fAmPms = newUnicodeStringArray(count);
1077    uprv_arrayCopy(amPmsArray,fAmPms,count);
1078    fAmPmsCount = count;
1079}
1080
1081const UnicodeString**
1082DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
1083{
1084    const UnicodeString **result = NULL;
1085
1086    umtx_lock(&LOCK);
1087    if (fZoneStrings == NULL) {
1088        if (fLocaleZoneStrings == NULL) {
1089            ((DateFormatSymbols*)this)->initZoneStringsArray();
1090        }
1091        result = (const UnicodeString**)fLocaleZoneStrings;
1092    } else {
1093        result = (const UnicodeString**)fZoneStrings;
1094    }
1095    rowCount = fZoneStringsRowCount;
1096    columnCount = fZoneStringsColCount;
1097    umtx_unlock(&LOCK);
1098
1099    return result;
1100}
1101
1102// For now, we include all zones
1103#define ZONE_SET UCAL_ZONE_TYPE_ANY
1104
1105// This code must be called within a synchronized block
1106void
1107DateFormatSymbols::initZoneStringsArray(void) {
1108    if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
1109        return;
1110    }
1111
1112    UErrorCode status = U_ZERO_ERROR;
1113
1114    StringEnumeration *tzids = NULL;
1115    UnicodeString ** zarray = NULL;
1116    TimeZoneNames *tzNames = NULL;
1117    int32_t rows = 0;
1118
1119    do { // dummy do-while
1120
1121        tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
1122        rows = tzids->count(status);
1123        if (U_FAILURE(status)) {
1124            break;
1125        }
1126
1127        // Allocate array
1128        int32_t size = rows * sizeof(UnicodeString*);
1129        zarray = (UnicodeString**)uprv_malloc(size);
1130        if (zarray == NULL) {
1131            status = U_MEMORY_ALLOCATION_ERROR;
1132            break;
1133        }
1134        uprv_memset(zarray, 0, size);
1135
1136        tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1137
1138        const UnicodeString *tzid;
1139        int32_t i = 0;
1140        UDate now = Calendar::getNow();
1141        UnicodeString tzDispName;
1142
1143        while ((tzid = tzids->snext(status))) {
1144            if (U_FAILURE(status)) {
1145                break;
1146            }
1147
1148            zarray[i] = new UnicodeString[5];
1149            if (zarray[i] == NULL) {
1150                status = U_MEMORY_ALLOCATION_ERROR;
1151                break;
1152            }
1153
1154            zarray[i][0].setTo(*tzid);
1155            zarray[i][1].setTo(tzNames->getDisplayName(*tzid, UTZNM_LONG_STANDARD, now, tzDispName));
1156            zarray[i][2].setTo(tzNames->getDisplayName(*tzid, UTZNM_SHORT_STANDARD, now, tzDispName));
1157            zarray[i][3].setTo(tzNames->getDisplayName(*tzid, UTZNM_LONG_DAYLIGHT, now, tzDispName));
1158            zarray[i][4].setTo(tzNames->getDisplayName(*tzid, UTZNM_SHORT_DAYLIGHT, now, tzDispName));
1159            i++;
1160        }
1161
1162    } while (FALSE);
1163
1164    if (U_FAILURE(status)) {
1165        if (zarray) {
1166            for (int32_t i = 0; i < rows; i++) {
1167                if (zarray[i]) {
1168                    delete[] zarray[i];
1169                }
1170            }
1171            uprv_free(zarray);
1172        }
1173    }
1174
1175    if (tzNames) {
1176        delete tzNames;
1177    }
1178    if (tzids) {
1179        delete tzids;
1180    }
1181
1182    fLocaleZoneStrings = zarray;
1183    fZoneStringsRowCount = rows;
1184    fZoneStringsColCount = 5;
1185}
1186
1187void
1188DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1189{
1190    // since deleting a 2-d array is a pain in the butt, we offload that task to
1191    // a separate function
1192    disposeZoneStrings();
1193    // we always own the new list, which we create here (we duplicate rather
1194    // than adopting the list passed in)
1195    fZoneStringsRowCount = rowCount;
1196    fZoneStringsColCount = columnCount;
1197    createZoneStrings((const UnicodeString**)strings);
1198}
1199
1200//------------------------------------------------------
1201
1202const UChar * U_EXPORT2
1203DateFormatSymbols::getPatternUChars(void)
1204{
1205    return gPatternChars;
1206}
1207
1208UDateFormatField U_EXPORT2
1209DateFormatSymbols::getPatternCharIndex(UChar c) {
1210    const UChar *p = u_strchr(gPatternChars, c);
1211    if (p == NULL) {
1212        return UDAT_FIELD_COUNT;
1213    } else {
1214        return static_cast<UDateFormatField>(p - gPatternChars);
1215    }
1216}
1217
1218static const uint64_t kNumericFieldsAlways =
1219    ((uint64_t)1 << UDAT_YEAR_FIELD) |                      // y
1220    ((uint64_t)1 << UDAT_DATE_FIELD) |                      // d
1221    ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) |              // k
1222    ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) |              // H
1223    ((uint64_t)1 << UDAT_MINUTE_FIELD) |                    // m
1224    ((uint64_t)1 << UDAT_SECOND_FIELD) |                    // s
1225    ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) |         // S
1226    ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) |               // D
1227    ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) |      // F
1228    ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) |              // w
1229    ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) |             // W
1230    ((uint64_t)1 << UDAT_HOUR1_FIELD) |                     // h
1231    ((uint64_t)1 << UDAT_HOUR0_FIELD) |                     // K
1232    ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) |                  // Y
1233    ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) |             // u
1234    ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) |                // g
1235    ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) |       // A
1236    ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD);               // r
1237
1238static const uint64_t kNumericFieldsForCount12 =
1239    ((uint64_t)1 << UDAT_MONTH_FIELD) |                     // M or MM
1240    ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) |                 // e or ee
1241    ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) |            // c or cc
1242    ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) |          // L or LL
1243    ((uint64_t)1 << UDAT_QUARTER_FIELD) |                   // Q or QQ
1244    ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD);         // q or qq
1245
1246UBool U_EXPORT2
1247DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1248    if (f == UDAT_FIELD_COUNT) {
1249        return FALSE;
1250    }
1251    uint64_t flag = ((uint64_t)1 << f);
1252    return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
1253}
1254
1255UBool U_EXPORT2
1256DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
1257    return isNumericField(getPatternCharIndex(c), count);
1258}
1259
1260//------------------------------------------------------
1261
1262UnicodeString&
1263DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1264{
1265    // fastCopyFrom() - see assignArray comments
1266    return result.fastCopyFrom(fLocalPatternChars);
1267}
1268
1269//------------------------------------------------------
1270
1271void
1272DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1273{
1274    fLocalPatternChars = newLocalPatternChars;
1275}
1276
1277//------------------------------------------------------
1278
1279static void
1280initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) {
1281    if (U_SUCCESS(status)) {
1282        int32_t strLen = 0;
1283        length = ures_getSize(data);
1284        *field = newUnicodeStringArray(length);
1285        if (*field) {
1286            for(int32_t i = 0; i<length; i++) {
1287                const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status);
1288                // setTo() - see assignArray comments
1289                (*(field)+i)->setTo(TRUE, resStr, strLen);
1290            }
1291        }
1292        else {
1293            length = 0;
1294            status = U_MEMORY_ALLOCATION_ERROR;
1295        }
1296    }
1297}
1298
1299static void
1300initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1301    if (U_SUCCESS(status)) {
1302        length = numStr;
1303        *field = newUnicodeStringArray((size_t)numStr);
1304        if (*field) {
1305            for(int32_t i = 0; i<length; i++) {
1306                // readonly aliases - all "data" strings are constant
1307                // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1308                (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1309            }
1310        }
1311        else {
1312            length = 0;
1313            status = U_MEMORY_ALLOCATION_ERROR;
1314        }
1315    }
1316}
1317
1318static void
1319initLeapMonthPattern(UnicodeString *field, int32_t index, const UResourceBundle *data, UErrorCode &status) {
1320    field[index].remove();
1321    if (U_SUCCESS(status)) {
1322        int32_t strLen = 0;
1323        const UChar *resStr = ures_getStringByKey(data, gNamesLeapTag, &strLen, &status);
1324        if (U_SUCCESS(status)) {
1325            field[index].setTo(TRUE, resStr, strLen);
1326        }
1327    }
1328    status = U_ZERO_ERROR;
1329}
1330
1331typedef struct {
1332    const char * usageTypeName;
1333    DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1334} ContextUsageTypeNameToEnumValue;
1335
1336static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1337   // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1338    { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1339    { "day-narrow",     DateFormatSymbols::kCapContextUsageDayNarrow },
1340    { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1341    { "era-abbr",       DateFormatSymbols::kCapContextUsageEraAbbrev },
1342    { "era-name",       DateFormatSymbols::kCapContextUsageEraWide },
1343    { "era-narrow",     DateFormatSymbols::kCapContextUsageEraNarrow },
1344    { "metazone-long",  DateFormatSymbols::kCapContextUsageMetazoneLong },
1345    { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1346    { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1347    { "month-narrow",   DateFormatSymbols::kCapContextUsageMonthNarrow },
1348    { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1349    { "zone-long",      DateFormatSymbols::kCapContextUsageZoneLong },
1350    { "zone-short",     DateFormatSymbols::kCapContextUsageZoneShort },
1351    { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1352};
1353
1354void
1355DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
1356{
1357    int32_t i;
1358    int32_t len = 0;
1359    const UChar *resStr;
1360    /* In case something goes wrong, initialize all of the data to NULL. */
1361    fEras = NULL;
1362    fErasCount = 0;
1363    fEraNames = NULL;
1364    fEraNamesCount = 0;
1365    fNarrowEras = NULL;
1366    fNarrowErasCount = 0;
1367    fMonths = NULL;
1368    fMonthsCount=0;
1369    fShortMonths = NULL;
1370    fShortMonthsCount=0;
1371    fNarrowMonths = NULL;
1372    fNarrowMonthsCount=0;
1373    fStandaloneMonths = NULL;
1374    fStandaloneMonthsCount=0;
1375    fStandaloneShortMonths = NULL;
1376    fStandaloneShortMonthsCount=0;
1377    fStandaloneNarrowMonths = NULL;
1378    fStandaloneNarrowMonthsCount=0;
1379    fWeekdays = NULL;
1380    fWeekdaysCount=0;
1381    fShortWeekdays = NULL;
1382    fShortWeekdaysCount=0;
1383    fShorterWeekdays = NULL;
1384    fShorterWeekdaysCount=0;
1385    fNarrowWeekdays = NULL;
1386    fNarrowWeekdaysCount=0;
1387    fStandaloneWeekdays = NULL;
1388    fStandaloneWeekdaysCount=0;
1389    fStandaloneShortWeekdays = NULL;
1390    fStandaloneShortWeekdaysCount=0;
1391    fStandaloneShorterWeekdays = NULL;
1392    fStandaloneShorterWeekdaysCount=0;
1393    fStandaloneNarrowWeekdays = NULL;
1394    fStandaloneNarrowWeekdaysCount=0;
1395    fAmPms = NULL;
1396    fAmPmsCount=0;
1397    fQuarters = NULL;
1398    fQuartersCount = 0;
1399    fShortQuarters = NULL;
1400    fShortQuartersCount = 0;
1401    fStandaloneQuarters = NULL;
1402    fStandaloneQuartersCount = 0;
1403    fStandaloneShortQuarters = NULL;
1404    fStandaloneShortQuartersCount = 0;
1405    fLeapMonthPatterns = NULL;
1406    fLeapMonthPatternsCount = 0;
1407    fShortYearNames = NULL;
1408    fShortYearNamesCount = 0;
1409    fShortZodiacNames = NULL;
1410    fShortZodiacNamesCount = 0;
1411    fZoneStringsRowCount = 0;
1412    fZoneStringsColCount = 0;
1413    fZoneStrings = NULL;
1414    fLocaleZoneStrings = NULL;
1415    uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
1416
1417    // We need to preserve the requested locale for
1418    // lazy ZoneStringFormat instantiation.  ZoneStringFormat
1419    // is region sensitive, thus, bundle locale bundle's locale
1420    // is not sufficient.
1421    fZSFLocale = locale;
1422
1423    if (U_FAILURE(status)) return;
1424
1425    /**
1426     * Retrieve the string arrays we need from the resource bundle file.
1427     * We cast away const here, but that's okay; we won't delete any of
1428     * these.
1429     */
1430    CalendarData calData(locale, type, status);
1431
1432    // load the first data item
1433    UResourceBundle *erasMain = calData.getByKey(gErasTag, status);
1434    UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1435    UErrorCode oldStatus = status;
1436    UResourceBundle *eraNames = ures_getByKeyWithFallback(erasMain, gNamesWideTag, NULL, &status);
1437    if ( status == U_MISSING_RESOURCE_ERROR ) { // Workaround because eras/wide was omitted from CLDR 1.3
1438       status = oldStatus;
1439       eraNames = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1440    }
1441    // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
1442    oldStatus = status;
1443    UResourceBundle *narrowEras = ures_getByKeyWithFallback(erasMain, gNamesNarrowTag, NULL, &status);
1444    if ( status == U_MISSING_RESOURCE_ERROR ) {
1445       status = oldStatus;
1446       narrowEras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1447    }
1448
1449    UErrorCode tempStatus = U_ZERO_ERROR;
1450    UResourceBundle *monthPatterns = calData.getByKey(gMonthPatternsTag, tempStatus);
1451    if (U_SUCCESS(tempStatus) && monthPatterns != NULL) {
1452        fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
1453        if (fLeapMonthPatterns) {
1454            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calData.getByKey2(gMonthPatternsTag, gNamesWideTag, tempStatus), tempStatus);
1455            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calData.getByKey2(gMonthPatternsTag, gNamesAbbrTag, tempStatus), tempStatus);
1456            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calData.getByKey2(gMonthPatternsTag, gNamesNarrowTag, tempStatus), tempStatus);
1457            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
1458            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
1459            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
1460            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calData.getByKey3(gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
1461            if (U_SUCCESS(tempStatus)) {
1462                fLeapMonthPatternsCount = kMonthPatternsCount;
1463            } else {
1464                delete[] fLeapMonthPatterns;
1465                fLeapMonthPatterns = NULL;
1466            }
1467        }
1468    }
1469
1470    tempStatus = U_ZERO_ERROR;
1471    UResourceBundle *cyclicNameSets= calData.getByKey(gCyclicNameSetsTag, tempStatus);
1472    if (U_SUCCESS(tempStatus) && cyclicNameSets != NULL) {
1473        UResourceBundle *nameSetYears = ures_getByKeyWithFallback(cyclicNameSets, gNameSetYearsTag, NULL, &tempStatus);
1474        if (U_SUCCESS(tempStatus)) {
1475            UResourceBundle *nameSetYearsFmt = ures_getByKeyWithFallback(nameSetYears, gNamesFormatTag, NULL, &tempStatus);
1476            if (U_SUCCESS(tempStatus)) {
1477                UResourceBundle *nameSetYearsFmtAbbrev = ures_getByKeyWithFallback(nameSetYearsFmt, gNamesAbbrTag, NULL, &tempStatus);
1478                if (U_SUCCESS(tempStatus)) {
1479                    initField(&fShortYearNames, fShortYearNamesCount, nameSetYearsFmtAbbrev, tempStatus);
1480                    ures_close(nameSetYearsFmtAbbrev);
1481                }
1482                ures_close(nameSetYearsFmt);
1483            }
1484            ures_close(nameSetYears);
1485        }
1486        UResourceBundle *nameSetZodiacs = ures_getByKeyWithFallback(cyclicNameSets, gNameSetZodiacsTag, NULL, &tempStatus);
1487        if (U_SUCCESS(tempStatus)) {
1488            UResourceBundle *nameSetZodiacsFmt = ures_getByKeyWithFallback(nameSetZodiacs, gNamesFormatTag, NULL, &tempStatus);
1489            if (U_SUCCESS(tempStatus)) {
1490                UResourceBundle *nameSetZodiacsFmtAbbrev = ures_getByKeyWithFallback(nameSetZodiacsFmt, gNamesAbbrTag, NULL, &tempStatus);
1491                if (U_SUCCESS(tempStatus)) {
1492                    initField(&fShortZodiacNames, fShortZodiacNamesCount, nameSetZodiacsFmtAbbrev, tempStatus);
1493                    ures_close(nameSetZodiacsFmtAbbrev);
1494                }
1495                ures_close(nameSetZodiacsFmt);
1496            }
1497            ures_close(nameSetZodiacs);
1498        }
1499    }
1500
1501    tempStatus = U_ZERO_ERROR;
1502    UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
1503    if (U_SUCCESS(tempStatus)) {
1504        UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
1505        if (U_SUCCESS(tempStatus)) {
1506            UResourceBundle *contextTransformUsage;
1507            while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
1508                const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
1509                if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
1510                    const char* usageType = ures_getKey(contextTransformUsage);
1511                    if (usageType != NULL) {
1512                        const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
1513                        int32_t compResult = 0;
1514                        // linear search; list is short and we cannot be sure that bsearch is available
1515                        while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
1516                            ++typeMapPtr;
1517                        }
1518                        if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
1519                            fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0];
1520                            fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1];
1521                        }
1522                    }
1523                }
1524                tempStatus = U_ZERO_ERROR;
1525                ures_close(contextTransformUsage);
1526            }
1527            ures_close(contextTransforms);
1528        }
1529        ures_close(localeBundle);
1530    }
1531
1532    UResourceBundle *weekdaysData = NULL; // Data closed by calData
1533    UResourceBundle *abbrWeekdaysData = NULL; // Data closed by calData
1534    UResourceBundle *shorterWeekdaysData = NULL; // Data closed by calData
1535    UResourceBundle *narrowWeekdaysData = NULL; // Data closed by calData
1536    UResourceBundle *standaloneWeekdaysData = NULL; // Data closed by calData
1537    UResourceBundle *standaloneAbbrWeekdaysData = NULL; // Data closed by calData
1538    UResourceBundle *standaloneShorterWeekdaysData = NULL; // Data closed by calData
1539    UResourceBundle *standaloneNarrowWeekdaysData = NULL; // Data closed by calData
1540
1541    U_LOCALE_BASED(locBased, *this);
1542    if (U_FAILURE(status))
1543    {
1544        if (useLastResortData)
1545        {
1546            // Handle the case in which there is no resource data present.
1547            // We don't have to generate usable patterns in this situation;
1548            // we just need to produce something that will be semi-intelligible
1549            // in most locales.
1550
1551            status = U_USING_FALLBACK_WARNING;
1552
1553            initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1554            initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1555            initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1556            initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
1557            initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1558            initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1559            initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
1560            initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1561            initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1562            initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1563            initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1564            initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1565            initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1566            initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1567            initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1568            initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1569            initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1570            initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
1571            initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1572            initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1573            initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1574            initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1575            fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1576        }
1577        goto cleanup;
1578    }
1579
1580    // if we make it to here, the resource data is cool, and we can get everything out
1581    // of it that we need except for the time-zone and localized-pattern data, which
1582    // are stored in a separate file
1583    locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status),
1584                          ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status));
1585
1586    initField(&fEras, fErasCount, eras, status);
1587    initField(&fEraNames, fEraNamesCount, eraNames, status);
1588    initField(&fNarrowEras, fNarrowErasCount, narrowEras, status);
1589
1590    initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1591    initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1592
1593    initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1594    if(status == U_MISSING_RESOURCE_ERROR) {
1595        status = U_ZERO_ERROR;
1596        initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1597    }
1598    if ( status == U_MISSING_RESOURCE_ERROR ) { /* If format/narrow not available, use format/abbreviated */
1599       status = U_ZERO_ERROR;
1600       initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1601    }
1602
1603    initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1604    if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/wide not available, use format/wide */
1605       status = U_ZERO_ERROR;
1606       initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1607    }
1608    initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1609    if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/abbreviated not available, use format/abbreviated */
1610       status = U_ZERO_ERROR;
1611       initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1612    }
1613    initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1614    if ( status == U_MISSING_RESOURCE_ERROR ) { /* if standalone/narrow not availabe, try format/narrow */
1615       status = U_ZERO_ERROR;
1616       initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1617       if ( status == U_MISSING_RESOURCE_ERROR ) { /* if still not there, use format/abbreviated */
1618          status = U_ZERO_ERROR;
1619          initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1620       }
1621    }
1622    initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status);
1623
1624    initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1625    initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1626
1627    initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1628    if(status == U_MISSING_RESOURCE_ERROR) {
1629        status = U_ZERO_ERROR;
1630        initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1631    }
1632
1633    initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1634    if(status == U_MISSING_RESOURCE_ERROR) {
1635        status = U_ZERO_ERROR;
1636        initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1637    }
1638
1639    // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
1640    /*
1641    // fastCopyFrom()/setTo() - see assignArray comments
1642    resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
1643    fLocalPatternChars.setTo(TRUE, resStr, len);
1644    // If the locale data does not include new pattern chars, use the defaults
1645    // TODO: Consider making this an error, since this may add conflicting characters.
1646    if (len < PATTERN_CHARS_LEN) {
1647        fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
1648    }
1649    */
1650    fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1651
1652    // Format wide weekdays -> fWeekdays
1653    // {sfb} fixed to handle 1-based weekdays
1654    weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1655    fWeekdaysCount = ures_getSize(weekdaysData);
1656    fWeekdays = new UnicodeString[fWeekdaysCount+1];
1657    /* pin the blame on system. If we cannot get a chunk of memory .. the system is dying!*/
1658    if (fWeekdays == NULL) {
1659        status = U_MEMORY_ALLOCATION_ERROR;
1660        goto cleanup;
1661    }
1662    // leave fWeekdays[0] empty
1663    for(i = 0; i<fWeekdaysCount; i++) {
1664        resStr = ures_getStringByIndex(weekdaysData, i, &len, &status);
1665        // setTo() - see assignArray comments
1666        fWeekdays[i+1].setTo(TRUE, resStr, len);
1667    }
1668    fWeekdaysCount++;
1669
1670    // Format abbreviated weekdays -> fShortWeekdays
1671    abbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1672    fShortWeekdaysCount = ures_getSize(abbrWeekdaysData);
1673    fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1];
1674    /* test for NULL */
1675    if (fShortWeekdays == 0) {
1676        status = U_MEMORY_ALLOCATION_ERROR;
1677        goto cleanup;
1678    }
1679    // leave fShortWeekdays[0] empty
1680    for(i = 0; i<fShortWeekdaysCount; i++) {
1681        resStr = ures_getStringByIndex(abbrWeekdaysData, i, &len, &status);
1682        // setTo() - see assignArray comments
1683        fShortWeekdays[i+1].setTo(TRUE, resStr, len);
1684    }
1685    fShortWeekdaysCount++;
1686
1687   // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
1688    shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesShortTag, status);
1689    if ( status == U_MISSING_RESOURCE_ERROR ) {
1690       status = U_ZERO_ERROR;
1691       shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1692    }
1693    fShorterWeekdaysCount = ures_getSize(shorterWeekdaysData);
1694    fShorterWeekdays = new UnicodeString[fShorterWeekdaysCount+1];
1695    /* test for NULL */
1696    if (fShorterWeekdays == 0) {
1697        status = U_MEMORY_ALLOCATION_ERROR;
1698        goto cleanup;
1699    }
1700    // leave fShorterWeekdays[0] empty
1701    for(i = 0; i<fShorterWeekdaysCount; i++) {
1702        resStr = ures_getStringByIndex(shorterWeekdaysData, i, &len, &status);
1703        // setTo() - see assignArray comments
1704        fShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1705    }
1706    fShorterWeekdaysCount++;
1707
1708   // Format narrow weekdays -> fNarrowWeekdays
1709    narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1710    if(status == U_MISSING_RESOURCE_ERROR) {
1711        status = U_ZERO_ERROR;
1712        narrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1713    }
1714    if ( status == U_MISSING_RESOURCE_ERROR ) {
1715       status = U_ZERO_ERROR;
1716       narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1717    }
1718    fNarrowWeekdaysCount = ures_getSize(narrowWeekdaysData);
1719    fNarrowWeekdays = new UnicodeString[fNarrowWeekdaysCount+1];
1720    /* test for NULL */
1721    if (fNarrowWeekdays == 0) {
1722        status = U_MEMORY_ALLOCATION_ERROR;
1723        goto cleanup;
1724    }
1725    // leave fNarrowWeekdays[0] empty
1726    for(i = 0; i<fNarrowWeekdaysCount; i++) {
1727        resStr = ures_getStringByIndex(narrowWeekdaysData, i, &len, &status);
1728        // setTo() - see assignArray comments
1729        fNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1730    }
1731    fNarrowWeekdaysCount++;
1732
1733   // Stand-alone wide weekdays -> fStandaloneWeekdays
1734    standaloneWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status);
1735    if ( status == U_MISSING_RESOURCE_ERROR ) {
1736       status = U_ZERO_ERROR;
1737       standaloneWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1738    }
1739    fStandaloneWeekdaysCount = ures_getSize(standaloneWeekdaysData);
1740    fStandaloneWeekdays = new UnicodeString[fStandaloneWeekdaysCount+1];
1741    /* test for NULL */
1742    if (fStandaloneWeekdays == 0) {
1743        status = U_MEMORY_ALLOCATION_ERROR;
1744        goto cleanup;
1745    }
1746    // leave fStandaloneWeekdays[0] empty
1747    for(i = 0; i<fStandaloneWeekdaysCount; i++) {
1748        resStr = ures_getStringByIndex(standaloneWeekdaysData, i, &len, &status);
1749        // setTo() - see assignArray comments
1750        fStandaloneWeekdays[i+1].setTo(TRUE, resStr, len);
1751    }
1752    fStandaloneWeekdaysCount++;
1753
1754   // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
1755    standaloneAbbrWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status);
1756    if ( status == U_MISSING_RESOURCE_ERROR ) {
1757       status = U_ZERO_ERROR;
1758       standaloneAbbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1759    }
1760    fStandaloneShortWeekdaysCount = ures_getSize(standaloneAbbrWeekdaysData);
1761    fStandaloneShortWeekdays = new UnicodeString[fStandaloneShortWeekdaysCount+1];
1762    /* test for NULL */
1763    if (fStandaloneShortWeekdays == 0) {
1764        status = U_MEMORY_ALLOCATION_ERROR;
1765        goto cleanup;
1766    }
1767    // leave fStandaloneShortWeekdays[0] empty
1768    for(i = 0; i<fStandaloneShortWeekdaysCount; i++) {
1769        resStr = ures_getStringByIndex(standaloneAbbrWeekdaysData, i, &len, &status);
1770        // setTo() - see assignArray comments
1771        fStandaloneShortWeekdays[i+1].setTo(TRUE, resStr, len);
1772    }
1773    fStandaloneShortWeekdaysCount++;
1774
1775    // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
1776    standaloneShorterWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status);
1777    if ( status == U_MISSING_RESOURCE_ERROR ) {
1778       status = U_ZERO_ERROR;
1779       standaloneShorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1780    }
1781    fStandaloneShorterWeekdaysCount = ures_getSize(standaloneShorterWeekdaysData);
1782    fStandaloneShorterWeekdays = new UnicodeString[fStandaloneShorterWeekdaysCount+1];
1783    /* test for NULL */
1784    if (fStandaloneShorterWeekdays == 0) {
1785        status = U_MEMORY_ALLOCATION_ERROR;
1786        goto cleanup;
1787    }
1788    // leave fStandaloneShorterWeekdays[0] empty
1789    for(i = 0; i<fStandaloneShorterWeekdaysCount; i++) {
1790        resStr = ures_getStringByIndex(standaloneShorterWeekdaysData, i, &len, &status);
1791        // setTo() - see assignArray comments
1792        fStandaloneShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1793    }
1794    fStandaloneShorterWeekdaysCount++;
1795
1796    // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
1797    standaloneNarrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1798    if ( status == U_MISSING_RESOURCE_ERROR ) {
1799       status = U_ZERO_ERROR;
1800       standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1801       if ( status == U_MISSING_RESOURCE_ERROR ) {
1802          status = U_ZERO_ERROR;
1803          standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1804       }
1805    }
1806    fStandaloneNarrowWeekdaysCount = ures_getSize(standaloneNarrowWeekdaysData);
1807    fStandaloneNarrowWeekdays = new UnicodeString[fStandaloneNarrowWeekdaysCount+1];
1808    /* test for NULL */
1809    if (fStandaloneNarrowWeekdays == 0) {
1810        status = U_MEMORY_ALLOCATION_ERROR;
1811        goto cleanup;
1812    }
1813    // leave fStandaloneNarrowWeekdays[0] empty
1814    for(i = 0; i<fStandaloneNarrowWeekdaysCount; i++) {
1815        resStr = ures_getStringByIndex(standaloneNarrowWeekdaysData, i, &len, &status);
1816        // setTo() - see assignArray comments
1817        fStandaloneNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1818    }
1819    fStandaloneNarrowWeekdaysCount++;
1820
1821cleanup:
1822    ures_close(eras);
1823    ures_close(eraNames);
1824    ures_close(narrowEras);
1825}
1826
1827Locale
1828DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
1829    U_LOCALE_BASED(locBased, *this);
1830    return locBased.getLocale(type, status);
1831}
1832
1833U_NAMESPACE_END
1834
1835#endif /* #if !UCONFIG_NO_FORMATTING */
1836
1837//eof
1838