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