1/*
2*******************************************************************************
3* Copyright (C) 1997-2013, 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 34
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    // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXx
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, 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 uint32_t kNumericFields =
1202    ((uint32_t)1 << UDAT_YEAR_FIELD) |                      // y
1203    ((uint32_t)1 << UDAT_MONTH_FIELD) |                     // M or MM
1204    ((uint32_t)1 << UDAT_DATE_FIELD) |                      // d
1205    ((uint32_t)1 << UDAT_HOUR_OF_DAY1_FIELD) |              // k
1206    ((uint32_t)1 << UDAT_HOUR_OF_DAY0_FIELD) |              // H
1207    ((uint32_t)1 << UDAT_MINUTE_FIELD) |                    // m
1208    ((uint32_t)1 << UDAT_SECOND_FIELD) |                    // s
1209    ((uint32_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) |         // S
1210    ((uint32_t)1 << UDAT_DAY_OF_YEAR_FIELD) |               // D
1211    ((uint32_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) |      // F
1212    ((uint32_t)1 << UDAT_WEEK_OF_YEAR_FIELD) |              // w
1213    ((uint32_t)1 << UDAT_WEEK_OF_MONTH_FIELD) |             // W
1214    ((uint32_t)1 << UDAT_HOUR1_FIELD) |                     // h
1215    ((uint32_t)1 << UDAT_HOUR0_FIELD) |                     // K
1216    ((uint32_t)1 << UDAT_YEAR_WOY_FIELD) |                  // Y
1217    ((uint32_t)1 << UDAT_DOW_LOCAL_FIELD) |                 // e
1218    ((uint32_t)1 << UDAT_EXTENDED_YEAR_FIELD);              // u
1219
1220UBool U_EXPORT2
1221DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1222    return
1223        f != UDAT_FIELD_COUNT &&
1224        (kNumericFields & ((uint32_t)1 << f)) != 0 &&
1225        (f != UDAT_MONTH_FIELD || count < 3);
1226}
1227
1228UBool U_EXPORT2
1229DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
1230    return isNumericField(getPatternCharIndex(c), count);
1231}
1232
1233//------------------------------------------------------
1234
1235UnicodeString&
1236DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1237{
1238    // fastCopyFrom() - see assignArray comments
1239    return result.fastCopyFrom(fLocalPatternChars);
1240}
1241
1242//------------------------------------------------------
1243
1244void
1245DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1246{
1247    fLocalPatternChars = newLocalPatternChars;
1248}
1249
1250//------------------------------------------------------
1251
1252static void
1253initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) {
1254    if (U_SUCCESS(status)) {
1255        int32_t strLen = 0;
1256        length = ures_getSize(data);
1257        *field = newUnicodeStringArray(length);
1258        if (*field) {
1259            for(int32_t i = 0; i<length; i++) {
1260                const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status);
1261                // setTo() - see assignArray comments
1262                (*(field)+i)->setTo(TRUE, resStr, strLen);
1263            }
1264        }
1265        else {
1266            length = 0;
1267            status = U_MEMORY_ALLOCATION_ERROR;
1268        }
1269    }
1270}
1271
1272static void
1273initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1274    if (U_SUCCESS(status)) {
1275        length = numStr;
1276        *field = newUnicodeStringArray((size_t)numStr);
1277        if (*field) {
1278            for(int32_t i = 0; i<length; i++) {
1279                // readonly aliases - all "data" strings are constant
1280                // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1281                (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1282            }
1283        }
1284        else {
1285            length = 0;
1286            status = U_MEMORY_ALLOCATION_ERROR;
1287        }
1288    }
1289}
1290
1291static void
1292initLeapMonthPattern(UnicodeString *field, int32_t index, const UResourceBundle *data, UErrorCode &status) {
1293    field[index].remove();
1294    if (U_SUCCESS(status)) {
1295        int32_t strLen = 0;
1296        const UChar *resStr = ures_getStringByKey(data, gNamesLeapTag, &strLen, &status);
1297        if (U_SUCCESS(status)) {
1298            field[index].setTo(TRUE, resStr, strLen);
1299        }
1300    }
1301    status = U_ZERO_ERROR;
1302}
1303
1304typedef struct {
1305    const char * usageTypeName;
1306    DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1307} ContextUsageTypeNameToEnumValue;
1308
1309static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1310   // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1311    { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1312    { "day-narrow",     DateFormatSymbols::kCapContextUsageDayNarrow },
1313    { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1314    { "era-abbr",       DateFormatSymbols::kCapContextUsageEraAbbrev },
1315    { "era-name",       DateFormatSymbols::kCapContextUsageEraWide },
1316    { "era-narrow",     DateFormatSymbols::kCapContextUsageEraNarrow },
1317    { "metazone-long",  DateFormatSymbols::kCapContextUsageMetazoneLong },
1318    { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1319    { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1320    { "month-narrow",   DateFormatSymbols::kCapContextUsageMonthNarrow },
1321    { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1322    { "zone-long",      DateFormatSymbols::kCapContextUsageZoneLong },
1323    { "zone-short",     DateFormatSymbols::kCapContextUsageZoneShort },
1324    { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1325};
1326
1327void
1328DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
1329{
1330    int32_t i;
1331    int32_t len = 0;
1332    const UChar *resStr;
1333    /* In case something goes wrong, initialize all of the data to NULL. */
1334    fEras = NULL;
1335    fErasCount = 0;
1336    fEraNames = NULL;
1337    fEraNamesCount = 0;
1338    fNarrowEras = NULL;
1339    fNarrowErasCount = 0;
1340    fMonths = NULL;
1341    fMonthsCount=0;
1342    fShortMonths = NULL;
1343    fShortMonthsCount=0;
1344    fNarrowMonths = NULL;
1345    fNarrowMonthsCount=0;
1346    fStandaloneMonths = NULL;
1347    fStandaloneMonthsCount=0;
1348    fStandaloneShortMonths = NULL;
1349    fStandaloneShortMonthsCount=0;
1350    fStandaloneNarrowMonths = NULL;
1351    fStandaloneNarrowMonthsCount=0;
1352    fWeekdays = NULL;
1353    fWeekdaysCount=0;
1354    fShortWeekdays = NULL;
1355    fShortWeekdaysCount=0;
1356    fShorterWeekdays = NULL;
1357    fShorterWeekdaysCount=0;
1358    fNarrowWeekdays = NULL;
1359    fNarrowWeekdaysCount=0;
1360    fStandaloneWeekdays = NULL;
1361    fStandaloneWeekdaysCount=0;
1362    fStandaloneShortWeekdays = NULL;
1363    fStandaloneShortWeekdaysCount=0;
1364    fStandaloneShorterWeekdays = NULL;
1365    fStandaloneShorterWeekdaysCount=0;
1366    fStandaloneNarrowWeekdays = NULL;
1367    fStandaloneNarrowWeekdaysCount=0;
1368    fAmPms = NULL;
1369    fAmPmsCount=0;
1370    fQuarters = NULL;
1371    fQuartersCount = 0;
1372    fShortQuarters = NULL;
1373    fShortQuartersCount = 0;
1374    fStandaloneQuarters = NULL;
1375    fStandaloneQuartersCount = 0;
1376    fStandaloneShortQuarters = NULL;
1377    fStandaloneShortQuartersCount = 0;
1378    fLeapMonthPatterns = NULL;
1379    fLeapMonthPatternsCount = 0;
1380    fShortYearNames = NULL;
1381    fShortYearNamesCount = 0;
1382    fZoneStringsRowCount = 0;
1383    fZoneStringsColCount = 0;
1384    fZoneStrings = NULL;
1385    fLocaleZoneStrings = NULL;
1386    uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
1387
1388    // We need to preserve the requested locale for
1389    // lazy ZoneStringFormat instantiation.  ZoneStringFormat
1390    // is region sensitive, thus, bundle locale bundle's locale
1391    // is not sufficient.
1392    fZSFLocale = locale;
1393
1394    if (U_FAILURE(status)) return;
1395
1396    /**
1397     * Retrieve the string arrays we need from the resource bundle file.
1398     * We cast away const here, but that's okay; we won't delete any of
1399     * these.
1400     */
1401    CalendarData calData(locale, type, status);
1402
1403    // load the first data item
1404    UResourceBundle *erasMain = calData.getByKey(gErasTag, status);
1405    UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1406    UErrorCode oldStatus = status;
1407    UResourceBundle *eraNames = ures_getByKeyWithFallback(erasMain, gNamesWideTag, NULL, &status);
1408    if ( status == U_MISSING_RESOURCE_ERROR ) { // Workaround because eras/wide was omitted from CLDR 1.3
1409       status = oldStatus;
1410       eraNames = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1411    }
1412    // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
1413    oldStatus = status;
1414    UResourceBundle *narrowEras = ures_getByKeyWithFallback(erasMain, gNamesNarrowTag, NULL, &status);
1415    if ( status == U_MISSING_RESOURCE_ERROR ) {
1416       status = oldStatus;
1417       narrowEras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1418    }
1419
1420    UErrorCode tempStatus = U_ZERO_ERROR;
1421    UResourceBundle *monthPatterns = calData.getByKey(gMonthPatternsTag, tempStatus);
1422    if (U_SUCCESS(tempStatus) && monthPatterns != NULL) {
1423        fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
1424        if (fLeapMonthPatterns) {
1425            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calData.getByKey2(gMonthPatternsTag, gNamesWideTag, tempStatus), tempStatus);
1426            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calData.getByKey2(gMonthPatternsTag, gNamesAbbrTag, tempStatus), tempStatus);
1427            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calData.getByKey2(gMonthPatternsTag, gNamesNarrowTag, tempStatus), tempStatus);
1428            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
1429            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
1430            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
1431            initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calData.getByKey3(gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
1432            if (U_SUCCESS(tempStatus)) {
1433                fLeapMonthPatternsCount = kMonthPatternsCount;
1434            } else {
1435                delete[] fLeapMonthPatterns;
1436                fLeapMonthPatterns = NULL;
1437            }
1438        }
1439    }
1440
1441    tempStatus = U_ZERO_ERROR;
1442    UResourceBundle *cyclicNameSets= calData.getByKey(gCyclicNameSetsTag, tempStatus);
1443    if (U_SUCCESS(tempStatus) && cyclicNameSets != NULL) {
1444        UResourceBundle *nameSetYears = ures_getByKeyWithFallback(cyclicNameSets, gNameSetYearsTag, NULL, &tempStatus);
1445        if (U_SUCCESS(tempStatus)) {
1446            UResourceBundle *nameSetYearsFmt = ures_getByKeyWithFallback(nameSetYears, gNamesFormatTag, NULL, &tempStatus);
1447            if (U_SUCCESS(tempStatus)) {
1448                UResourceBundle *nameSetYearsFmtAbbrev = ures_getByKeyWithFallback(nameSetYearsFmt, gNamesAbbrTag, NULL, &tempStatus);
1449                if (U_SUCCESS(tempStatus)) {
1450                    initField(&fShortYearNames, fShortYearNamesCount, nameSetYearsFmtAbbrev, tempStatus);
1451                    ures_close(nameSetYearsFmtAbbrev);
1452                }
1453                ures_close(nameSetYearsFmt);
1454            }
1455            ures_close(nameSetYears);
1456        }
1457    }
1458
1459    tempStatus = U_ZERO_ERROR;
1460    UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
1461    if (U_SUCCESS(tempStatus)) {
1462        UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
1463        if (U_SUCCESS(tempStatus)) {
1464            UResourceBundle *contextTransformUsage;
1465            while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
1466                const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
1467                if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
1468                    const char* usageType = ures_getKey(contextTransformUsage);
1469                    if (usageType != NULL) {
1470                        const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
1471                        int32_t compResult = 0;
1472                        // linear search; list is short and we cannot be sure that bsearch is available
1473                        while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
1474                            ++typeMapPtr;
1475                        }
1476                        if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
1477                            fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0];
1478                            fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1];
1479                        }
1480                    }
1481                }
1482                tempStatus = U_ZERO_ERROR;
1483                ures_close(contextTransformUsage);
1484            }
1485            ures_close(contextTransforms);
1486        }
1487        ures_close(localeBundle);
1488    }
1489
1490    UResourceBundle *weekdaysData = NULL; // Data closed by calData
1491    UResourceBundle *abbrWeekdaysData = NULL; // Data closed by calData
1492    UResourceBundle *shorterWeekdaysData = NULL; // Data closed by calData
1493    UResourceBundle *narrowWeekdaysData = NULL; // Data closed by calData
1494    UResourceBundle *standaloneWeekdaysData = NULL; // Data closed by calData
1495    UResourceBundle *standaloneAbbrWeekdaysData = NULL; // Data closed by calData
1496    UResourceBundle *standaloneShorterWeekdaysData = NULL; // Data closed by calData
1497    UResourceBundle *standaloneNarrowWeekdaysData = NULL; // Data closed by calData
1498
1499    U_LOCALE_BASED(locBased, *this);
1500    if (U_FAILURE(status))
1501    {
1502        if (useLastResortData)
1503        {
1504            // Handle the case in which there is no resource data present.
1505            // We don't have to generate usable patterns in this situation;
1506            // we just need to produce something that will be semi-intelligible
1507            // in most locales.
1508
1509            status = U_USING_FALLBACK_WARNING;
1510
1511            initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1512            initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1513            initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1514            initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
1515            initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1516            initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1517            initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
1518            initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1519            initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1520            initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1521            initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1522            initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1523            initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1524            initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1525            initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1526            initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1527            initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1528            initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
1529            initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1530            initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1531            initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1532            initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1533            fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1534        }
1535        goto cleanup;
1536    }
1537
1538    // if we make it to here, the resource data is cool, and we can get everything out
1539    // of it that we need except for the time-zone and localized-pattern data, which
1540    // are stored in a separate file
1541    locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status),
1542                          ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status));
1543
1544    initField(&fEras, fErasCount, eras, status);
1545    initField(&fEraNames, fEraNamesCount, eraNames, status);
1546    initField(&fNarrowEras, fNarrowErasCount, narrowEras, status);
1547
1548    initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1549    initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1550
1551    initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1552    if(status == U_MISSING_RESOURCE_ERROR) {
1553        status = U_ZERO_ERROR;
1554        initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1555    }
1556    if ( status == U_MISSING_RESOURCE_ERROR ) { /* If format/narrow not available, use format/abbreviated */
1557       status = U_ZERO_ERROR;
1558       initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1559    }
1560
1561    initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1562    if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/wide not available, use format/wide */
1563       status = U_ZERO_ERROR;
1564       initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1565    }
1566    initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1567    if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/abbreviated not available, use format/abbreviated */
1568       status = U_ZERO_ERROR;
1569       initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1570    }
1571    initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1572    if ( status == U_MISSING_RESOURCE_ERROR ) { /* if standalone/narrow not availabe, try format/narrow */
1573       status = U_ZERO_ERROR;
1574       initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1575       if ( status == U_MISSING_RESOURCE_ERROR ) { /* if still not there, use format/abbreviated */
1576          status = U_ZERO_ERROR;
1577          initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1578       }
1579    }
1580    initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status);
1581
1582    initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1583    initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1584
1585    initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1586    if(status == U_MISSING_RESOURCE_ERROR) {
1587        status = U_ZERO_ERROR;
1588        initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1589    }
1590
1591    initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1592    if(status == U_MISSING_RESOURCE_ERROR) {
1593        status = U_ZERO_ERROR;
1594        initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1595    }
1596
1597    // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
1598    /*
1599    // fastCopyFrom()/setTo() - see assignArray comments
1600    resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
1601    fLocalPatternChars.setTo(TRUE, resStr, len);
1602    // If the locale data does not include new pattern chars, use the defaults
1603    // TODO: Consider making this an error, since this may add conflicting characters.
1604    if (len < PATTERN_CHARS_LEN) {
1605        fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
1606    }
1607    */
1608    fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1609
1610    // Format wide weekdays -> fWeekdays
1611    // {sfb} fixed to handle 1-based weekdays
1612    weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1613    fWeekdaysCount = ures_getSize(weekdaysData);
1614    fWeekdays = new UnicodeString[fWeekdaysCount+1];
1615    /* pin the blame on system. If we cannot get a chunk of memory .. the system is dying!*/
1616    if (fWeekdays == NULL) {
1617        status = U_MEMORY_ALLOCATION_ERROR;
1618        goto cleanup;
1619    }
1620    // leave fWeekdays[0] empty
1621    for(i = 0; i<fWeekdaysCount; i++) {
1622        resStr = ures_getStringByIndex(weekdaysData, i, &len, &status);
1623        // setTo() - see assignArray comments
1624        fWeekdays[i+1].setTo(TRUE, resStr, len);
1625    }
1626    fWeekdaysCount++;
1627
1628    // Format abbreviated weekdays -> fShortWeekdays
1629    abbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1630    fShortWeekdaysCount = ures_getSize(abbrWeekdaysData);
1631    fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1];
1632    /* test for NULL */
1633    if (fShortWeekdays == 0) {
1634        status = U_MEMORY_ALLOCATION_ERROR;
1635        goto cleanup;
1636    }
1637    // leave fShortWeekdays[0] empty
1638    for(i = 0; i<fShortWeekdaysCount; i++) {
1639        resStr = ures_getStringByIndex(abbrWeekdaysData, i, &len, &status);
1640        // setTo() - see assignArray comments
1641        fShortWeekdays[i+1].setTo(TRUE, resStr, len);
1642    }
1643    fShortWeekdaysCount++;
1644
1645   // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
1646    shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesShortTag, status);
1647    if ( status == U_MISSING_RESOURCE_ERROR ) {
1648       status = U_ZERO_ERROR;
1649       shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1650    }
1651    fShorterWeekdaysCount = ures_getSize(shorterWeekdaysData);
1652    fShorterWeekdays = new UnicodeString[fShorterWeekdaysCount+1];
1653    /* test for NULL */
1654    if (fShorterWeekdays == 0) {
1655        status = U_MEMORY_ALLOCATION_ERROR;
1656        goto cleanup;
1657    }
1658    // leave fShorterWeekdays[0] empty
1659    for(i = 0; i<fShorterWeekdaysCount; i++) {
1660        resStr = ures_getStringByIndex(shorterWeekdaysData, i, &len, &status);
1661        // setTo() - see assignArray comments
1662        fShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1663    }
1664    fShorterWeekdaysCount++;
1665
1666   // Format narrow weekdays -> fNarrowWeekdays
1667    narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1668    if(status == U_MISSING_RESOURCE_ERROR) {
1669        status = U_ZERO_ERROR;
1670        narrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1671    }
1672    if ( status == U_MISSING_RESOURCE_ERROR ) {
1673       status = U_ZERO_ERROR;
1674       narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1675    }
1676    fNarrowWeekdaysCount = ures_getSize(narrowWeekdaysData);
1677    fNarrowWeekdays = new UnicodeString[fNarrowWeekdaysCount+1];
1678    /* test for NULL */
1679    if (fNarrowWeekdays == 0) {
1680        status = U_MEMORY_ALLOCATION_ERROR;
1681        goto cleanup;
1682    }
1683    // leave fNarrowWeekdays[0] empty
1684    for(i = 0; i<fNarrowWeekdaysCount; i++) {
1685        resStr = ures_getStringByIndex(narrowWeekdaysData, i, &len, &status);
1686        // setTo() - see assignArray comments
1687        fNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1688    }
1689    fNarrowWeekdaysCount++;
1690
1691   // Stand-alone wide weekdays -> fStandaloneWeekdays
1692    standaloneWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status);
1693    if ( status == U_MISSING_RESOURCE_ERROR ) {
1694       status = U_ZERO_ERROR;
1695       standaloneWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1696    }
1697    fStandaloneWeekdaysCount = ures_getSize(standaloneWeekdaysData);
1698    fStandaloneWeekdays = new UnicodeString[fStandaloneWeekdaysCount+1];
1699    /* test for NULL */
1700    if (fStandaloneWeekdays == 0) {
1701        status = U_MEMORY_ALLOCATION_ERROR;
1702        goto cleanup;
1703    }
1704    // leave fStandaloneWeekdays[0] empty
1705    for(i = 0; i<fStandaloneWeekdaysCount; i++) {
1706        resStr = ures_getStringByIndex(standaloneWeekdaysData, i, &len, &status);
1707        // setTo() - see assignArray comments
1708        fStandaloneWeekdays[i+1].setTo(TRUE, resStr, len);
1709    }
1710    fStandaloneWeekdaysCount++;
1711
1712   // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
1713    standaloneAbbrWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status);
1714    if ( status == U_MISSING_RESOURCE_ERROR ) {
1715       status = U_ZERO_ERROR;
1716       standaloneAbbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1717    }
1718    fStandaloneShortWeekdaysCount = ures_getSize(standaloneAbbrWeekdaysData);
1719    fStandaloneShortWeekdays = new UnicodeString[fStandaloneShortWeekdaysCount+1];
1720    /* test for NULL */
1721    if (fStandaloneShortWeekdays == 0) {
1722        status = U_MEMORY_ALLOCATION_ERROR;
1723        goto cleanup;
1724    }
1725    // leave fStandaloneShortWeekdays[0] empty
1726    for(i = 0; i<fStandaloneShortWeekdaysCount; i++) {
1727        resStr = ures_getStringByIndex(standaloneAbbrWeekdaysData, i, &len, &status);
1728        // setTo() - see assignArray comments
1729        fStandaloneShortWeekdays[i+1].setTo(TRUE, resStr, len);
1730    }
1731    fStandaloneShortWeekdaysCount++;
1732
1733    // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
1734    standaloneShorterWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status);
1735    if ( status == U_MISSING_RESOURCE_ERROR ) {
1736       status = U_ZERO_ERROR;
1737       standaloneShorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1738    }
1739    fStandaloneShorterWeekdaysCount = ures_getSize(standaloneShorterWeekdaysData);
1740    fStandaloneShorterWeekdays = new UnicodeString[fStandaloneShorterWeekdaysCount+1];
1741    /* test for NULL */
1742    if (fStandaloneShorterWeekdays == 0) {
1743        status = U_MEMORY_ALLOCATION_ERROR;
1744        goto cleanup;
1745    }
1746    // leave fStandaloneShorterWeekdays[0] empty
1747    for(i = 0; i<fStandaloneShorterWeekdaysCount; i++) {
1748        resStr = ures_getStringByIndex(standaloneShorterWeekdaysData, i, &len, &status);
1749        // setTo() - see assignArray comments
1750        fStandaloneShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1751    }
1752    fStandaloneShorterWeekdaysCount++;
1753
1754    // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
1755    standaloneNarrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1756    if ( status == U_MISSING_RESOURCE_ERROR ) {
1757       status = U_ZERO_ERROR;
1758       standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1759       if ( status == U_MISSING_RESOURCE_ERROR ) {
1760          status = U_ZERO_ERROR;
1761          standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1762       }
1763    }
1764    fStandaloneNarrowWeekdaysCount = ures_getSize(standaloneNarrowWeekdaysData);
1765    fStandaloneNarrowWeekdays = new UnicodeString[fStandaloneNarrowWeekdaysCount+1];
1766    /* test for NULL */
1767    if (fStandaloneNarrowWeekdays == 0) {
1768        status = U_MEMORY_ALLOCATION_ERROR;
1769        goto cleanup;
1770    }
1771    // leave fStandaloneNarrowWeekdays[0] empty
1772    for(i = 0; i<fStandaloneNarrowWeekdaysCount; i++) {
1773        resStr = ures_getStringByIndex(standaloneNarrowWeekdaysData, i, &len, &status);
1774        // setTo() - see assignArray comments
1775        fStandaloneNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1776    }
1777    fStandaloneNarrowWeekdaysCount++;
1778
1779cleanup:
1780    ures_close(eras);
1781    ures_close(eraNames);
1782    ures_close(narrowEras);
1783}
1784
1785Locale
1786DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
1787    U_LOCALE_BASED(locBased, *this);
1788    return locBased.getLocale(type, status);
1789}
1790
1791U_NAMESPACE_END
1792
1793#endif /* #if !UCONFIG_NO_FORMATTING */
1794
1795//eof
1796