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