Home | History | Annotate | Download | only in i18n
      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  */
     56 static 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.
     72 static 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.
     90 static 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.
    103 static 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.
    112 static const UChar gLastResortAmPmMarkers[2][3] =
    113 {
    114     {0x0041, 0x004D, 0x0000}, /* "AM" */
    115     {0x0050, 0x004D, 0x0000}  /* "PM" */
    116 };
    117 
    118 static 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 */
    125 typedef 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 
    148 U_NAMESPACE_BEGIN
    149 
    150 UOBJECT_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  */
    158 static const char gErasTag[]="eras";
    159 static const char gCyclicNameSetsTag[]="cyclicNameSets";
    160 static const char gNameSetYearsTag[]="years";
    161 static const char gMonthNamesTag[]="monthNames";
    162 static const char gMonthPatternsTag[]="monthPatterns";
    163 static const char gDayNamesTag[]="dayNames";
    164 static const char gNamesWideTag[]="wide";
    165 static const char gNamesAbbrTag[]="abbreviated";
    166 static const char gNamesShortTag[]="short";
    167 static const char gNamesNarrowTag[]="narrow";
    168 static const char gNamesAllTag[]="all";
    169 static const char gNamesLeapTag[]="leap";
    170 static const char gNamesFormatTag[]="format";
    171 static const char gNamesStandaloneTag[]="stand-alone";
    172 static const char gNamesNumericTag[]="numeric";
    173 static const char gAmPmMarkersTag[]="AmPmMarkers";
    174 static const char gQuartersTag[]="quarters";
    175 
    176 // static const char gZoneStringsTag[]="zoneStrings";
    177 
    178 // static const char gLocalPatternCharsTag[]="localPatternChars";
    179 
    180 static const char gContextTransformsTag[]="contextTransforms";
    181 
    182 static 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  */
    188 static inline UnicodeString* newUnicodeStringArray(size_t count) {
    189     return new UnicodeString[count ? count : 1];
    190 }
    191 
    192 //------------------------------------------------------
    193 
    194 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
    195                                      UErrorCode& status)
    196     : UObject()
    197 {
    198   initializeData(locale, NULL,  status);
    199 }
    200 
    201 DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
    202     : UObject()
    203 {
    204   initializeData(Locale::getDefault(), NULL, status, TRUE);
    205 }
    206 
    207 
    208 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
    209                                      const char *type,
    210                                      UErrorCode& status)
    211     : UObject()
    212 {
    213   initializeData(locale, type,  status);
    214 }
    215 
    216 DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
    217     : UObject()
    218 {
    219   initializeData(Locale::getDefault(), type, status, TRUE);
    220 }
    221 
    222 DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
    223     : UObject(other)
    224 {
    225     copyData(other);
    226 }
    227 
    228 void
    229 DateFormatSymbols::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  */
    261 void
    262 DateFormatSymbols::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  */
    295 void
    296 DateFormatSymbols::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  */
    355 DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
    356 {
    357     dispose();
    358     copyData(other);
    359 
    360     return *this;
    361 }
    362 
    363 DateFormatSymbols::~DateFormatSymbols()
    364 {
    365     dispose();
    366 }
    367 
    368 void 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 
    398 void 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 
    419 UBool
    420 DateFormatSymbols::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 
    433 UBool
    434 DateFormatSymbols::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 
    515 const UnicodeString*
    516 DateFormatSymbols::getEras(int32_t &count) const
    517 {
    518     count = fErasCount;
    519     return fEras;
    520 }
    521 
    522 const UnicodeString*
    523 DateFormatSymbols::getEraNames(int32_t &count) const
    524 {
    525     count = fEraNamesCount;
    526     return fEraNames;
    527 }
    528 
    529 const UnicodeString*
    530 DateFormatSymbols::getNarrowEras(int32_t &count) const
    531 {
    532     count = fNarrowErasCount;
    533     return fNarrowEras;
    534 }
    535 
    536 const UnicodeString*
    537 DateFormatSymbols::getMonths(int32_t &count) const
    538 {
    539     count = fMonthsCount;
    540     return fMonths;
    541 }
    542 
    543 const UnicodeString*
    544 DateFormatSymbols::getShortMonths(int32_t &count) const
    545 {
    546     count = fShortMonthsCount;
    547     return fShortMonths;
    548 }
    549 
    550 const UnicodeString*
    551 DateFormatSymbols::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 
    600 const UnicodeString*
    601 DateFormatSymbols::getWeekdays(int32_t &count) const
    602 {
    603     count = fWeekdaysCount;
    604     return fWeekdays;
    605 }
    606 
    607 const UnicodeString*
    608 DateFormatSymbols::getShortWeekdays(int32_t &count) const
    609 {
    610     count = fShortWeekdaysCount;
    611     return fShortWeekdays;
    612 }
    613 
    614 const UnicodeString*
    615 DateFormatSymbols::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 
    669 const UnicodeString*
    670 DateFormatSymbols::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 
    719 const UnicodeString*
    720 DateFormatSymbols::getAmPmStrings(int32_t &count) const
    721 {
    722     count = fAmPmsCount;
    723     return fAmPms;
    724 }
    725 
    726 const UnicodeString*
    727 DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
    728 {
    729     count = fLeapMonthPatternsCount;
    730     return fLeapMonthPatterns;
    731 }
    732 
    733 //------------------------------------------------------
    734 
    735 void
    736 DateFormatSymbols::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 
    749 void
    750 DateFormatSymbols::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 
    763 void
    764 DateFormatSymbols::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 
    777 void
    778 DateFormatSymbols::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 
    791 void
    792 DateFormatSymbols::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 
    805 void
    806 DateFormatSymbols::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 
    872 void 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 
    885 void
    886 DateFormatSymbols::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 
    899 void
    900 DateFormatSymbols::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 
    980 void
    981 DateFormatSymbols::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 
   1051 void
   1052 DateFormatSymbols::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 
   1064 const UnicodeString**
   1065 DateFormatSymbols::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
   1089 void
   1090 DateFormatSymbols::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 
   1170 void
   1171 DateFormatSymbols::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 
   1185 const UChar * U_EXPORT2
   1186 DateFormatSymbols::getPatternUChars(void)
   1187 {
   1188     return gPatternChars;
   1189 }
   1190 
   1191 UDateFormatField U_EXPORT2
   1192 DateFormatSymbols::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 
   1201 static 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 
   1220 UBool U_EXPORT2
   1221 DateFormatSymbols::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 
   1228 UBool U_EXPORT2
   1229 DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
   1230     return isNumericField(getPatternCharIndex(c), count);
   1231 }
   1232 
   1233 //------------------------------------------------------
   1234 
   1235 UnicodeString&
   1236 DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
   1237 {
   1238     // fastCopyFrom() - see assignArray comments
   1239     return result.fastCopyFrom(fLocalPatternChars);
   1240 }
   1241 
   1242 //------------------------------------------------------
   1243 
   1244 void
   1245 DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
   1246 {
   1247     fLocalPatternChars = newLocalPatternChars;
   1248 }
   1249 
   1250 //------------------------------------------------------
   1251 
   1252 static void
   1253 initField(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 
   1272 static void
   1273 initField(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 
   1291 static void
   1292 initLeapMonthPattern(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 
   1304 typedef struct {
   1305     const char * usageTypeName;
   1306     DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
   1307 } ContextUsageTypeNameToEnumValue;
   1308 
   1309 static 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 
   1327 void
   1328 DateFormatSymbols::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 
   1779 cleanup:
   1780     ures_close(eras);
   1781     ures_close(eraNames);
   1782     ures_close(narrowEras);
   1783 }
   1784 
   1785 Locale
   1786 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
   1787     U_LOCALE_BASED(locBased, *this);
   1788     return locBased.getLocale(type, status);
   1789 }
   1790 
   1791 U_NAMESPACE_END
   1792 
   1793 #endif /* #if !UCONFIG_NO_FORMATTING */
   1794 
   1795 //eof
   1796