Home | History | Annotate | Download | only in i18n
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *******************************************************************************
      5 * Copyright (C) 1997-2016, International Business Machines Corporation and    *
      6 * others. All Rights Reserved.                                                *
      7 *******************************************************************************
      8 *
      9 * File DTFMTSYM.CPP
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   02/19/97    aliu        Converted from java.
     15 *   07/21/98    stephen     Added getZoneIndex
     16 *                            Changed weekdays/short weekdays to be one-based
     17 *   06/14/99    stephen     Removed SimpleDateFormat::fgTimeZoneDataSuffix
     18 *   11/16/99    weiv        Added 'Y' and 'e' to fgPatternChars
     19 *   03/27/00    weiv        Keeping resource bundle around!
     20 *   06/30/05    emmons      Added eraNames, narrow month/day, standalone context
     21 *   10/12/05    emmons      Added setters for eraNames, month/day by width/context
     22 *******************************************************************************
     23 */
     24 #include "unicode/utypes.h"
     25 
     26 #if !UCONFIG_NO_FORMATTING
     27 #include "unicode/ustring.h"
     28 #include "unicode/localpointer.h"
     29 #include "unicode/dtfmtsym.h"
     30 #include "unicode/smpdtfmt.h"
     31 #include "unicode/msgfmt.h"
     32 #include "unicode/numsys.h"
     33 #include "unicode/tznames.h"
     34 #include "cpputils.h"
     35 #include "umutex.h"
     36 #include "cmemory.h"
     37 #include "cstring.h"
     38 #include "charstr.h"
     39 #include "dt_impl.h"
     40 #include "locbased.h"
     41 #include "gregoimp.h"
     42 #include "hash.h"
     43 #include "uassert.h"
     44 #include "uresimp.h"
     45 #include "ureslocs.h"
     46 #include "uvector.h"
     47 #include "shareddateformatsymbols.h"
     48 #include "unicode/calendar.h"
     49 #include "unifiedcache.h"
     50 
     51 // *****************************************************************************
     52 // class DateFormatSymbols
     53 // *****************************************************************************
     54 
     55 /**
     56  * These are static arrays we use only in the case where we have no
     57  * resource data.
     58  */
     59 
     60 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
     61 #define PATTERN_CHARS_LEN 38
     62 #else
     63 #define PATTERN_CHARS_LEN 37
     64 #endif
     65 
     66 /**
     67  * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
     68  * locales use the same these unlocalized pattern characters.
     69  */
     70 static const UChar gPatternChars[] = {
     71     // if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
     72     //   GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
     73     // else:
     74     //   GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
     75 
     76     0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
     77     0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
     78     0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
     79     0x55, 0x4F, 0x58, 0x78, 0x72, 0x62, 0x42,
     80 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
     81     0x3a,
     82 #endif
     83     0
     84 };
     85 
     86 //------------------------------------------------------
     87 // Strings of last resort.  These are only used if we have no resource
     88 // files.  They aren't designed for actual use, just for backup.
     89 
     90 // These are the month names and abbreviations of last resort.
     91 static const UChar gLastResortMonthNames[13][3] =
     92 {
     93     {0x0030, 0x0031, 0x0000}, /* "01" */
     94     {0x0030, 0x0032, 0x0000}, /* "02" */
     95     {0x0030, 0x0033, 0x0000}, /* "03" */
     96     {0x0030, 0x0034, 0x0000}, /* "04" */
     97     {0x0030, 0x0035, 0x0000}, /* "05" */
     98     {0x0030, 0x0036, 0x0000}, /* "06" */
     99     {0x0030, 0x0037, 0x0000}, /* "07" */
    100     {0x0030, 0x0038, 0x0000}, /* "08" */
    101     {0x0030, 0x0039, 0x0000}, /* "09" */
    102     {0x0031, 0x0030, 0x0000}, /* "10" */
    103     {0x0031, 0x0031, 0x0000}, /* "11" */
    104     {0x0031, 0x0032, 0x0000}, /* "12" */
    105     {0x0031, 0x0033, 0x0000}  /* "13" */
    106 };
    107 
    108 // These are the weekday names and abbreviations of last resort.
    109 static const UChar gLastResortDayNames[8][2] =
    110 {
    111     {0x0030, 0x0000}, /* "0" */
    112     {0x0031, 0x0000}, /* "1" */
    113     {0x0032, 0x0000}, /* "2" */
    114     {0x0033, 0x0000}, /* "3" */
    115     {0x0034, 0x0000}, /* "4" */
    116     {0x0035, 0x0000}, /* "5" */
    117     {0x0036, 0x0000}, /* "6" */
    118     {0x0037, 0x0000}  /* "7" */
    119 };
    120 
    121 // These are the quarter names and abbreviations of last resort.
    122 static const UChar gLastResortQuarters[4][2] =
    123 {
    124     {0x0031, 0x0000}, /* "1" */
    125     {0x0032, 0x0000}, /* "2" */
    126     {0x0033, 0x0000}, /* "3" */
    127     {0x0034, 0x0000}, /* "4" */
    128 };
    129 
    130 // These are the am/pm and BC/AD markers of last resort.
    131 static const UChar gLastResortAmPmMarkers[2][3] =
    132 {
    133     {0x0041, 0x004D, 0x0000}, /* "AM" */
    134     {0x0050, 0x004D, 0x0000}  /* "PM" */
    135 };
    136 
    137 static const UChar gLastResortEras[2][3] =
    138 {
    139     {0x0042, 0x0043, 0x0000}, /* "BC" */
    140     {0x0041, 0x0044, 0x0000}  /* "AD" */
    141 };
    142 
    143 /* Sizes for the last resort string arrays */
    144 typedef enum LastResortSize {
    145     kMonthNum = 13,
    146     kMonthLen = 3,
    147 
    148     kDayNum = 8,
    149     kDayLen = 2,
    150 
    151     kAmPmNum = 2,
    152     kAmPmLen = 3,
    153 
    154     kQuarterNum = 4,
    155     kQuarterLen = 2,
    156 
    157     kEraNum = 2,
    158     kEraLen = 3,
    159 
    160     kZoneNum = 5,
    161     kZoneLen = 4,
    162 
    163     kGmtHourNum = 4,
    164     kGmtHourLen = 10
    165 } LastResortSize;
    166 
    167 U_NAMESPACE_BEGIN
    168 
    169 SharedDateFormatSymbols::~SharedDateFormatSymbols() {
    170 }
    171 
    172 template<> U_I18N_API
    173 const SharedDateFormatSymbols *
    174         LocaleCacheKey<SharedDateFormatSymbols>::createObject(
    175                 const void * /*unusedContext*/, UErrorCode &status) const {
    176     char type[256];
    177     Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
    178     if (U_FAILURE(status)) {
    179         return NULL;
    180     }
    181     SharedDateFormatSymbols *shared
    182             = new SharedDateFormatSymbols(fLoc, type, status);
    183     if (shared == NULL) {
    184         status = U_MEMORY_ALLOCATION_ERROR;
    185         return NULL;
    186     }
    187     if (U_FAILURE(status)) {
    188         delete shared;
    189         return NULL;
    190     }
    191     shared->addRef();
    192     return shared;
    193 }
    194 
    195 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
    196 
    197 #define kSUPPLEMENTAL "supplementalData"
    198 
    199 /**
    200  * These are the tags we expect to see in normal resource bundle files associated
    201  * with a locale and calendar
    202  */
    203 static const char gCalendarTag[]="calendar";
    204 static const char gGregorianTag[]="gregorian";
    205 static const char gErasTag[]="eras";
    206 static const char gCyclicNameSetsTag[]="cyclicNameSets";
    207 static const char gNameSetYearsTag[]="years";
    208 static const char gNameSetZodiacsTag[]="zodiacs";
    209 static const char gMonthNamesTag[]="monthNames";
    210 static const char gMonthPatternsTag[]="monthPatterns";
    211 static const char gDayNamesTag[]="dayNames";
    212 static const char gNamesWideTag[]="wide";
    213 static const char gNamesAbbrTag[]="abbreviated";
    214 static const char gNamesShortTag[]="short";
    215 static const char gNamesNarrowTag[]="narrow";
    216 static const char gNamesAllTag[]="all";
    217 static const char gNamesFormatTag[]="format";
    218 static const char gNamesStandaloneTag[]="stand-alone";
    219 static const char gNamesNumericTag[]="numeric";
    220 static const char gAmPmMarkersTag[]="AmPmMarkers";
    221 static const char gAmPmMarkersAbbrTag[]="AmPmMarkersAbbr";
    222 static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow";
    223 static const char gQuartersTag[]="quarters";
    224 static const char gNumberElementsTag[]="NumberElements";
    225 static const char gSymbolsTag[]="symbols";
    226 static const char gTimeSeparatorTag[]="timeSeparator";
    227 static const char gDayPeriodTag[]="dayPeriod";
    228 
    229 // static const char gZoneStringsTag[]="zoneStrings";
    230 
    231 // static const char gLocalPatternCharsTag[]="localPatternChars";
    232 
    233 static const char gContextTransformsTag[]="contextTransforms";
    234 
    235 static UMutex LOCK = U_MUTEX_INITIALIZER;
    236 
    237 /**
    238  * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
    239  * Work around this.
    240  */
    241 static inline UnicodeString* newUnicodeStringArray(size_t count) {
    242     return new UnicodeString[count ? count : 1];
    243 }
    244 
    245 //------------------------------------------------------
    246 
    247 DateFormatSymbols * U_EXPORT2
    248 DateFormatSymbols::createForLocale(
    249         const Locale& locale, UErrorCode &status) {
    250     const SharedDateFormatSymbols *shared = NULL;
    251     UnifiedCache::getByLocale(locale, shared, status);
    252     if (U_FAILURE(status)) {
    253         return NULL;
    254     }
    255     DateFormatSymbols *result = new DateFormatSymbols(shared->get());
    256     shared->removeRef();
    257     if (result == NULL) {
    258         status = U_MEMORY_ALLOCATION_ERROR;
    259         return NULL;
    260     }
    261     return result;
    262 }
    263 
    264 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
    265                                      UErrorCode& status)
    266     : UObject()
    267 {
    268   initializeData(locale, NULL,  status);
    269 }
    270 
    271 DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
    272     : UObject()
    273 {
    274   initializeData(Locale::getDefault(), NULL, status, TRUE);
    275 }
    276 
    277 
    278 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
    279                                      const char *type,
    280                                      UErrorCode& status)
    281     : UObject()
    282 {
    283   initializeData(locale, type,  status);
    284 }
    285 
    286 DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
    287     : UObject()
    288 {
    289   initializeData(Locale::getDefault(), type, status, TRUE);
    290 }
    291 
    292 DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
    293     : UObject(other)
    294 {
    295     copyData(other);
    296 }
    297 
    298 void
    299 DateFormatSymbols::assignArray(UnicodeString*& dstArray,
    300                                int32_t& dstCount,
    301                                const UnicodeString* srcArray,
    302                                int32_t srcCount)
    303 {
    304     // assignArray() is only called by copyData() and initializeData(), which in turn
    305     // implements the copy constructor and the assignment operator.
    306     // All strings in a DateFormatSymbols object are created in one of the following
    307     // three ways that all allow to safely use UnicodeString::fastCopyFrom():
    308     // - readonly-aliases from resource bundles
    309     // - readonly-aliases or allocated strings from constants
    310     // - safely cloned strings (with owned buffers) from setXYZ() functions
    311     //
    312     // Note that this is true for as long as DateFormatSymbols can be constructed
    313     // only from a locale bundle or set via the cloning API,
    314     // *and* for as long as all the strings are in *private* fields, preventing
    315     // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
    316     dstCount = srcCount;
    317     dstArray = newUnicodeStringArray(srcCount);
    318     if(dstArray != NULL) {
    319         int32_t i;
    320         for(i=0; i<srcCount; ++i) {
    321             dstArray[i].fastCopyFrom(srcArray[i]);
    322         }
    323     }
    324 }
    325 
    326 /**
    327  * Create a copy, in fZoneStrings, of the given zone strings array.  The
    328  * member variables fZoneStringsRowCount and fZoneStringsColCount should
    329  * be set already by the caller.
    330  */
    331 void
    332 DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
    333 {
    334     int32_t row, col;
    335     UBool failed = FALSE;
    336 
    337     fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
    338     if (fZoneStrings != NULL) {
    339         for (row=0; row<fZoneStringsRowCount; ++row)
    340         {
    341             fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
    342             if (fZoneStrings[row] == NULL) {
    343                 failed = TRUE;
    344                 break;
    345             }
    346             for (col=0; col<fZoneStringsColCount; ++col) {
    347                 // fastCopyFrom() - see assignArray comments
    348                 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
    349             }
    350         }
    351     }
    352     // If memory allocation failed, roll back and delete fZoneStrings
    353     if (failed) {
    354         for (int i = row; i >= 0; i--) {
    355             delete[] fZoneStrings[i];
    356         }
    357         uprv_free(fZoneStrings);
    358         fZoneStrings = NULL;
    359     }
    360 }
    361 
    362 /**
    363  * Copy all of the other's data to this.
    364  */
    365 void
    366 DateFormatSymbols::copyData(const DateFormatSymbols& other) {
    367     UErrorCode status = U_ZERO_ERROR;
    368     U_LOCALE_BASED(locBased, *this);
    369     locBased.setLocaleIDs(
    370         other.getLocale(ULOC_VALID_LOCALE, status),
    371         other.getLocale(ULOC_ACTUAL_LOCALE, status));
    372     assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
    373     assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
    374     assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
    375     assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
    376     assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
    377     assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
    378     assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
    379     assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
    380     assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
    381     assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
    382     assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
    383     assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
    384     assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
    385     assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
    386     assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
    387     assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
    388     assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
    389     assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
    390     assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
    391     fTimeSeparator.fastCopyFrom(other.fTimeSeparator);  // fastCopyFrom() - see assignArray comments
    392     assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
    393     assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
    394     assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
    395     assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
    396     assignArray(fWideDayPeriods, fWideDayPeriodsCount,
    397                 other.fWideDayPeriods, other.fWideDayPeriodsCount);
    398     assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
    399                 other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
    400     assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
    401                 other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
    402     assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
    403                 other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
    404     assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
    405                 other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
    406     assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
    407                 other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
    408     if (other.fLeapMonthPatterns != NULL) {
    409         assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
    410     } else {
    411         fLeapMonthPatterns = NULL;
    412         fLeapMonthPatternsCount = 0;
    413     }
    414     if (other.fShortYearNames != NULL) {
    415         assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
    416     } else {
    417         fShortYearNames = NULL;
    418         fShortYearNamesCount = 0;
    419     }
    420     if (other.fShortZodiacNames != NULL) {
    421         assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
    422     } else {
    423         fShortZodiacNames = NULL;
    424         fShortZodiacNamesCount = 0;
    425     }
    426 
    427     if (other.fZoneStrings != NULL) {
    428         fZoneStringsColCount = other.fZoneStringsColCount;
    429         fZoneStringsRowCount = other.fZoneStringsRowCount;
    430         createZoneStrings((const UnicodeString**)other.fZoneStrings);
    431 
    432     } else {
    433         fZoneStrings = NULL;
    434         fZoneStringsColCount = 0;
    435         fZoneStringsRowCount = 0;
    436     }
    437     fZSFLocale = other.fZSFLocale;
    438     // Other zone strings data is created on demand
    439     fLocaleZoneStrings = NULL;
    440 
    441     // fastCopyFrom() - see assignArray comments
    442     fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
    443 
    444     uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
    445 }
    446 
    447 /**
    448  * Assignment operator.
    449  */
    450 DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
    451 {
    452     dispose();
    453     copyData(other);
    454 
    455     return *this;
    456 }
    457 
    458 DateFormatSymbols::~DateFormatSymbols()
    459 {
    460     dispose();
    461 }
    462 
    463 void DateFormatSymbols::dispose()
    464 {
    465     delete[] fEras;
    466     delete[] fEraNames;
    467     delete[] fNarrowEras;
    468     delete[] fMonths;
    469     delete[] fShortMonths;
    470     delete[] fNarrowMonths;
    471     delete[] fStandaloneMonths;
    472     delete[] fStandaloneShortMonths;
    473     delete[] fStandaloneNarrowMonths;
    474     delete[] fWeekdays;
    475     delete[] fShortWeekdays;
    476     delete[] fShorterWeekdays;
    477     delete[] fNarrowWeekdays;
    478     delete[] fStandaloneWeekdays;
    479     delete[] fStandaloneShortWeekdays;
    480     delete[] fStandaloneShorterWeekdays;
    481     delete[] fStandaloneNarrowWeekdays;
    482     delete[] fAmPms;
    483     delete[] fNarrowAmPms;
    484     delete[] fQuarters;
    485     delete[] fShortQuarters;
    486     delete[] fStandaloneQuarters;
    487     delete[] fStandaloneShortQuarters;
    488     delete[] fLeapMonthPatterns;
    489     delete[] fShortYearNames;
    490     delete[] fShortZodiacNames;
    491     delete[] fAbbreviatedDayPeriods;
    492     delete[] fWideDayPeriods;
    493     delete[] fNarrowDayPeriods;
    494     delete[] fStandaloneAbbreviatedDayPeriods;
    495     delete[] fStandaloneWideDayPeriods;
    496     delete[] fStandaloneNarrowDayPeriods;
    497 
    498     disposeZoneStrings();
    499 }
    500 
    501 void DateFormatSymbols::disposeZoneStrings()
    502 {
    503     if (fZoneStrings) {
    504         for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
    505             delete[] fZoneStrings[row];
    506         }
    507         uprv_free(fZoneStrings);
    508     }
    509     if (fLocaleZoneStrings) {
    510         for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
    511             delete[] fLocaleZoneStrings[row];
    512         }
    513         uprv_free(fLocaleZoneStrings);
    514     }
    515 
    516     fZoneStrings = NULL;
    517     fLocaleZoneStrings = NULL;
    518     fZoneStringsRowCount = 0;
    519     fZoneStringsColCount = 0;
    520 }
    521 
    522 UBool
    523 DateFormatSymbols::arrayCompare(const UnicodeString* array1,
    524                                 const UnicodeString* array2,
    525                                 int32_t count)
    526 {
    527     if (array1 == array2) return TRUE;
    528     while (count>0)
    529     {
    530         --count;
    531         if (array1[count] != array2[count]) return FALSE;
    532     }
    533     return TRUE;
    534 }
    535 
    536 UBool
    537 DateFormatSymbols::operator==(const DateFormatSymbols& other) const
    538 {
    539     // First do cheap comparisons
    540     if (this == &other) {
    541         return TRUE;
    542     }
    543     if (fErasCount == other.fErasCount &&
    544         fEraNamesCount == other.fEraNamesCount &&
    545         fNarrowErasCount == other.fNarrowErasCount &&
    546         fMonthsCount == other.fMonthsCount &&
    547         fShortMonthsCount == other.fShortMonthsCount &&
    548         fNarrowMonthsCount == other.fNarrowMonthsCount &&
    549         fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
    550         fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
    551         fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
    552         fWeekdaysCount == other.fWeekdaysCount &&
    553         fShortWeekdaysCount == other.fShortWeekdaysCount &&
    554         fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
    555         fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
    556         fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
    557         fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
    558         fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
    559         fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
    560         fAmPmsCount == other.fAmPmsCount &&
    561         fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
    562         fQuartersCount == other.fQuartersCount &&
    563         fShortQuartersCount == other.fShortQuartersCount &&
    564         fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
    565         fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
    566         fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
    567         fShortYearNamesCount == other.fShortYearNamesCount &&
    568         fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
    569         fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
    570         fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
    571         fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
    572         fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
    573         fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
    574         fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
    575         (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
    576     {
    577         // Now compare the arrays themselves
    578         if (arrayCompare(fEras, other.fEras, fErasCount) &&
    579             arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
    580             arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
    581             arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
    582             arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
    583             arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
    584             arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
    585             arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
    586             arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
    587             arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
    588             arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
    589             arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
    590             arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
    591             arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
    592             arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
    593             arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
    594             arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
    595             arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
    596             arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
    597             fTimeSeparator == other.fTimeSeparator &&
    598             arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
    599             arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
    600             arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
    601             arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
    602             arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
    603             arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
    604             arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
    605             arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
    606             arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
    607             arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
    608             arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
    609                          fStandaloneAbbreviatedDayPeriodsCount) &&
    610             arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
    611                          fStandaloneWideDayPeriodsCount) &&
    612             arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
    613                          fStandaloneWideDayPeriodsCount))
    614         {
    615             // Compare the contents of fZoneStrings
    616             if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
    617                 if (fZSFLocale == other.fZSFLocale) {
    618                     return TRUE;
    619                 }
    620             } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
    621                 if (fZoneStringsRowCount == other.fZoneStringsRowCount
    622                     && fZoneStringsColCount == other.fZoneStringsColCount) {
    623                     UBool cmpres = TRUE;
    624                     for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
    625                         cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
    626                     }
    627                     return cmpres;
    628                 }
    629             }
    630             return FALSE;
    631         }
    632     }
    633     return FALSE;
    634 }
    635 
    636 //------------------------------------------------------
    637 
    638 const UnicodeString*
    639 DateFormatSymbols::getEras(int32_t &count) const
    640 {
    641     count = fErasCount;
    642     return fEras;
    643 }
    644 
    645 const UnicodeString*
    646 DateFormatSymbols::getEraNames(int32_t &count) const
    647 {
    648     count = fEraNamesCount;
    649     return fEraNames;
    650 }
    651 
    652 const UnicodeString*
    653 DateFormatSymbols::getNarrowEras(int32_t &count) const
    654 {
    655     count = fNarrowErasCount;
    656     return fNarrowEras;
    657 }
    658 
    659 const UnicodeString*
    660 DateFormatSymbols::getMonths(int32_t &count) const
    661 {
    662     count = fMonthsCount;
    663     return fMonths;
    664 }
    665 
    666 const UnicodeString*
    667 DateFormatSymbols::getShortMonths(int32_t &count) const
    668 {
    669     count = fShortMonthsCount;
    670     return fShortMonths;
    671 }
    672 
    673 const UnicodeString*
    674 DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
    675 {
    676     UnicodeString *returnValue = NULL;
    677 
    678     switch (context) {
    679     case FORMAT :
    680         switch(width) {
    681         case WIDE :
    682             count = fMonthsCount;
    683             returnValue = fMonths;
    684             break;
    685         case ABBREVIATED :
    686         case SHORT : // no month data for this, defaults to ABBREVIATED
    687             count = fShortMonthsCount;
    688             returnValue = fShortMonths;
    689             break;
    690         case NARROW :
    691             count = fNarrowMonthsCount;
    692             returnValue = fNarrowMonths;
    693             break;
    694         case DT_WIDTH_COUNT :
    695             break;
    696         }
    697         break;
    698     case STANDALONE :
    699         switch(width) {
    700         case WIDE :
    701             count = fStandaloneMonthsCount;
    702             returnValue = fStandaloneMonths;
    703             break;
    704         case ABBREVIATED :
    705         case SHORT : // no month data for this, defaults to ABBREVIATED
    706             count = fStandaloneShortMonthsCount;
    707             returnValue = fStandaloneShortMonths;
    708             break;
    709         case NARROW :
    710             count = fStandaloneNarrowMonthsCount;
    711             returnValue = fStandaloneNarrowMonths;
    712             break;
    713         case DT_WIDTH_COUNT :
    714             break;
    715         }
    716         break;
    717     case DT_CONTEXT_COUNT :
    718         break;
    719     }
    720     return returnValue;
    721 }
    722 
    723 const UnicodeString*
    724 DateFormatSymbols::getWeekdays(int32_t &count) const
    725 {
    726     count = fWeekdaysCount;
    727     return fWeekdays;
    728 }
    729 
    730 const UnicodeString*
    731 DateFormatSymbols::getShortWeekdays(int32_t &count) const
    732 {
    733     count = fShortWeekdaysCount;
    734     return fShortWeekdays;
    735 }
    736 
    737 const UnicodeString*
    738 DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
    739 {
    740     UnicodeString *returnValue = NULL;
    741     switch (context) {
    742     case FORMAT :
    743         switch(width) {
    744             case WIDE :
    745                 count = fWeekdaysCount;
    746                 returnValue = fWeekdays;
    747                 break;
    748             case ABBREVIATED :
    749                 count = fShortWeekdaysCount;
    750                 returnValue = fShortWeekdays;
    751                 break;
    752             case SHORT :
    753                 count = fShorterWeekdaysCount;
    754                 returnValue = fShorterWeekdays;
    755                 break;
    756             case NARROW :
    757                 count = fNarrowWeekdaysCount;
    758                 returnValue = fNarrowWeekdays;
    759                 break;
    760             case DT_WIDTH_COUNT :
    761                 break;
    762         }
    763         break;
    764     case STANDALONE :
    765         switch(width) {
    766             case WIDE :
    767                 count = fStandaloneWeekdaysCount;
    768                 returnValue = fStandaloneWeekdays;
    769                 break;
    770             case ABBREVIATED :
    771                 count = fStandaloneShortWeekdaysCount;
    772                 returnValue = fStandaloneShortWeekdays;
    773                 break;
    774             case SHORT :
    775                 count = fStandaloneShorterWeekdaysCount;
    776                 returnValue = fStandaloneShorterWeekdays;
    777                 break;
    778             case NARROW :
    779                 count = fStandaloneNarrowWeekdaysCount;
    780                 returnValue = fStandaloneNarrowWeekdays;
    781                 break;
    782             case DT_WIDTH_COUNT :
    783                 break;
    784         }
    785         break;
    786     case DT_CONTEXT_COUNT :
    787         break;
    788     }
    789     return returnValue;
    790 }
    791 
    792 const UnicodeString*
    793 DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
    794 {
    795     UnicodeString *returnValue = NULL;
    796 
    797     switch (context) {
    798     case FORMAT :
    799         switch(width) {
    800         case WIDE :
    801             count = fQuartersCount;
    802             returnValue = fQuarters;
    803             break;
    804         case ABBREVIATED :
    805         case SHORT : // no quarter data for this, defaults to ABBREVIATED
    806             count = fShortQuartersCount;
    807             returnValue = fShortQuarters;
    808             break;
    809         case NARROW :
    810             count = 0;
    811             returnValue = NULL;
    812             break;
    813         case DT_WIDTH_COUNT :
    814             break;
    815         }
    816         break;
    817     case STANDALONE :
    818         switch(width) {
    819         case WIDE :
    820             count = fStandaloneQuartersCount;
    821             returnValue = fStandaloneQuarters;
    822             break;
    823         case ABBREVIATED :
    824         case SHORT : // no quarter data for this, defaults to ABBREVIATED
    825             count = fStandaloneShortQuartersCount;
    826             returnValue = fStandaloneShortQuarters;
    827             break;
    828         case NARROW :
    829             count = 0;
    830             returnValue = NULL;
    831             break;
    832         case DT_WIDTH_COUNT :
    833             break;
    834         }
    835         break;
    836     case DT_CONTEXT_COUNT :
    837         break;
    838     }
    839     return returnValue;
    840 }
    841 
    842 UnicodeString&
    843 DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
    844 {
    845     // fastCopyFrom() - see assignArray comments
    846     return result.fastCopyFrom(fTimeSeparator);
    847 }
    848 
    849 const UnicodeString*
    850 DateFormatSymbols::getAmPmStrings(int32_t &count) const
    851 {
    852     count = fAmPmsCount;
    853     return fAmPms;
    854 }
    855 
    856 const UnicodeString*
    857 DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
    858 {
    859     count = fLeapMonthPatternsCount;
    860     return fLeapMonthPatterns;
    861 }
    862 
    863 const UnicodeString*
    864 DateFormatSymbols::getYearNames(int32_t& count,
    865                                 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
    866 {
    867     count = fShortYearNamesCount;
    868     return fShortYearNames;
    869 }
    870 
    871 void
    872 DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
    873                                 DtContextType context, DtWidthType width)
    874 {
    875     if (context == FORMAT && width == ABBREVIATED) {
    876         if (fShortYearNames) {
    877             delete[] fShortYearNames;
    878         }
    879         fShortYearNames = newUnicodeStringArray(count);
    880         uprv_arrayCopy(yearNames, fShortYearNames, count);
    881         fShortYearNamesCount = count;
    882     }
    883 }
    884 
    885 const UnicodeString*
    886 DateFormatSymbols::getZodiacNames(int32_t& count,
    887                                 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
    888 {
    889     count = fShortZodiacNamesCount;
    890     return fShortZodiacNames;
    891 }
    892 
    893 void
    894 DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
    895                                 DtContextType context, DtWidthType width)
    896 {
    897     if (context == FORMAT && width == ABBREVIATED) {
    898         if (fShortZodiacNames) {
    899             delete[] fShortZodiacNames;
    900         }
    901         fShortZodiacNames = newUnicodeStringArray(count);
    902         uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
    903         fShortZodiacNamesCount = count;
    904     }
    905 }
    906 
    907 //------------------------------------------------------
    908 
    909 void
    910 DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
    911 {
    912     // delete the old list if we own it
    913     if (fEras)
    914         delete[] fEras;
    915 
    916     // we always own the new list, which we create here (we duplicate rather
    917     // than adopting the list passed in)
    918     fEras = newUnicodeStringArray(count);
    919     uprv_arrayCopy(erasArray,fEras,  count);
    920     fErasCount = count;
    921 }
    922 
    923 void
    924 DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
    925 {
    926     // delete the old list if we own it
    927     if (fEraNames)
    928         delete[] fEraNames;
    929 
    930     // we always own the new list, which we create here (we duplicate rather
    931     // than adopting the list passed in)
    932     fEraNames = newUnicodeStringArray(count);
    933     uprv_arrayCopy(eraNamesArray,fEraNames,  count);
    934     fEraNamesCount = count;
    935 }
    936 
    937 void
    938 DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
    939 {
    940     // delete the old list if we own it
    941     if (fNarrowEras)
    942         delete[] fNarrowEras;
    943 
    944     // we always own the new list, which we create here (we duplicate rather
    945     // than adopting the list passed in)
    946     fNarrowEras = newUnicodeStringArray(count);
    947     uprv_arrayCopy(narrowErasArray,fNarrowEras,  count);
    948     fNarrowErasCount = count;
    949 }
    950 
    951 void
    952 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
    953 {
    954     // delete the old list if we own it
    955     if (fMonths)
    956         delete[] fMonths;
    957 
    958     // we always own the new list, which we create here (we duplicate rather
    959     // than adopting the list passed in)
    960     fMonths = newUnicodeStringArray(count);
    961     uprv_arrayCopy( monthsArray,fMonths,count);
    962     fMonthsCount = count;
    963 }
    964 
    965 void
    966 DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
    967 {
    968     // delete the old list if we own it
    969     if (fShortMonths)
    970         delete[] fShortMonths;
    971 
    972     // we always own the new list, which we create here (we duplicate rather
    973     // than adopting the list passed in)
    974     fShortMonths = newUnicodeStringArray(count);
    975     uprv_arrayCopy(shortMonthsArray,fShortMonths,  count);
    976     fShortMonthsCount = count;
    977 }
    978 
    979 void
    980 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
    981 {
    982     // delete the old list if we own it
    983     // we always own the new list, which we create here (we duplicate rather
    984     // than adopting the list passed in)
    985 
    986     switch (context) {
    987     case FORMAT :
    988         switch (width) {
    989         case WIDE :
    990             if (fMonths)
    991                 delete[] fMonths;
    992             fMonths = newUnicodeStringArray(count);
    993             uprv_arrayCopy( monthsArray,fMonths,count);
    994             fMonthsCount = count;
    995             break;
    996         case ABBREVIATED :
    997             if (fShortMonths)
    998                 delete[] fShortMonths;
    999             fShortMonths = newUnicodeStringArray(count);
   1000             uprv_arrayCopy( monthsArray,fShortMonths,count);
   1001             fShortMonthsCount = count;
   1002             break;
   1003         case NARROW :
   1004             if (fNarrowMonths)
   1005                 delete[] fNarrowMonths;
   1006             fNarrowMonths = newUnicodeStringArray(count);
   1007             uprv_arrayCopy( monthsArray,fNarrowMonths,count);
   1008             fNarrowMonthsCount = count;
   1009             break;
   1010         default :
   1011             break;
   1012         }
   1013         break;
   1014     case STANDALONE :
   1015         switch (width) {
   1016         case WIDE :
   1017             if (fStandaloneMonths)
   1018                 delete[] fStandaloneMonths;
   1019             fStandaloneMonths = newUnicodeStringArray(count);
   1020             uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
   1021             fStandaloneMonthsCount = count;
   1022             break;
   1023         case ABBREVIATED :
   1024             if (fStandaloneShortMonths)
   1025                 delete[] fStandaloneShortMonths;
   1026             fStandaloneShortMonths = newUnicodeStringArray(count);
   1027             uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
   1028             fStandaloneShortMonthsCount = count;
   1029             break;
   1030         case NARROW :
   1031            if (fStandaloneNarrowMonths)
   1032                 delete[] fStandaloneNarrowMonths;
   1033             fStandaloneNarrowMonths = newUnicodeStringArray(count);
   1034             uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
   1035             fStandaloneNarrowMonthsCount = count;
   1036             break;
   1037         default :
   1038             break;
   1039         }
   1040         break;
   1041     case DT_CONTEXT_COUNT :
   1042         break;
   1043     }
   1044 }
   1045 
   1046 void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
   1047 {
   1048     // delete the old list if we own it
   1049     if (fWeekdays)
   1050         delete[] fWeekdays;
   1051 
   1052     // we always own the new list, which we create here (we duplicate rather
   1053     // than adopting the list passed in)
   1054     fWeekdays = newUnicodeStringArray(count);
   1055     uprv_arrayCopy(weekdaysArray,fWeekdays,count);
   1056     fWeekdaysCount = count;
   1057 }
   1058 
   1059 void
   1060 DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
   1061 {
   1062     // delete the old list if we own it
   1063     if (fShortWeekdays)
   1064         delete[] fShortWeekdays;
   1065 
   1066     // we always own the new list, which we create here (we duplicate rather
   1067     // than adopting the list passed in)
   1068     fShortWeekdays = newUnicodeStringArray(count);
   1069     uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
   1070     fShortWeekdaysCount = count;
   1071 }
   1072 
   1073 void
   1074 DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
   1075 {
   1076     // delete the old list if we own it
   1077     // we always own the new list, which we create here (we duplicate rather
   1078     // than adopting the list passed in)
   1079 
   1080     switch (context) {
   1081     case FORMAT :
   1082         switch (width) {
   1083         case WIDE :
   1084             if (fWeekdays)
   1085                 delete[] fWeekdays;
   1086             fWeekdays = newUnicodeStringArray(count);
   1087             uprv_arrayCopy(weekdaysArray, fWeekdays, count);
   1088             fWeekdaysCount = count;
   1089             break;
   1090         case ABBREVIATED :
   1091             if (fShortWeekdays)
   1092                 delete[] fShortWeekdays;
   1093             fShortWeekdays = newUnicodeStringArray(count);
   1094             uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
   1095             fShortWeekdaysCount = count;
   1096             break;
   1097         case SHORT :
   1098             if (fShorterWeekdays)
   1099                 delete[] fShorterWeekdays;
   1100             fShorterWeekdays = newUnicodeStringArray(count);
   1101             uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
   1102             fShorterWeekdaysCount = count;
   1103             break;
   1104         case NARROW :
   1105             if (fNarrowWeekdays)
   1106                 delete[] fNarrowWeekdays;
   1107             fNarrowWeekdays = newUnicodeStringArray(count);
   1108             uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
   1109             fNarrowWeekdaysCount = count;
   1110             break;
   1111         case DT_WIDTH_COUNT :
   1112             break;
   1113         }
   1114         break;
   1115     case STANDALONE :
   1116         switch (width) {
   1117         case WIDE :
   1118             if (fStandaloneWeekdays)
   1119                 delete[] fStandaloneWeekdays;
   1120             fStandaloneWeekdays = newUnicodeStringArray(count);
   1121             uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
   1122             fStandaloneWeekdaysCount = count;
   1123             break;
   1124         case ABBREVIATED :
   1125             if (fStandaloneShortWeekdays)
   1126                 delete[] fStandaloneShortWeekdays;
   1127             fStandaloneShortWeekdays = newUnicodeStringArray(count);
   1128             uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
   1129             fStandaloneShortWeekdaysCount = count;
   1130             break;
   1131         case SHORT :
   1132             if (fStandaloneShorterWeekdays)
   1133                 delete[] fStandaloneShorterWeekdays;
   1134             fStandaloneShorterWeekdays = newUnicodeStringArray(count);
   1135             uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
   1136             fStandaloneShorterWeekdaysCount = count;
   1137             break;
   1138         case NARROW :
   1139             if (fStandaloneNarrowWeekdays)
   1140                 delete[] fStandaloneNarrowWeekdays;
   1141             fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
   1142             uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
   1143             fStandaloneNarrowWeekdaysCount = count;
   1144             break;
   1145         case DT_WIDTH_COUNT :
   1146             break;
   1147         }
   1148         break;
   1149     case DT_CONTEXT_COUNT :
   1150         break;
   1151     }
   1152 }
   1153 
   1154 void
   1155 DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
   1156 {
   1157     // delete the old list if we own it
   1158     // we always own the new list, which we create here (we duplicate rather
   1159     // than adopting the list passed in)
   1160 
   1161     switch (context) {
   1162     case FORMAT :
   1163         switch (width) {
   1164         case WIDE :
   1165             if (fQuarters)
   1166                 delete[] fQuarters;
   1167             fQuarters = newUnicodeStringArray(count);
   1168             uprv_arrayCopy( quartersArray,fQuarters,count);
   1169             fQuartersCount = count;
   1170             break;
   1171         case ABBREVIATED :
   1172             if (fShortQuarters)
   1173                 delete[] fShortQuarters;
   1174             fShortQuarters = newUnicodeStringArray(count);
   1175             uprv_arrayCopy( quartersArray,fShortQuarters,count);
   1176             fShortQuartersCount = count;
   1177             break;
   1178         case NARROW :
   1179         /*
   1180             if (fNarrowQuarters)
   1181                 delete[] fNarrowQuarters;
   1182             fNarrowQuarters = newUnicodeStringArray(count);
   1183             uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
   1184             fNarrowQuartersCount = count;
   1185         */
   1186             break;
   1187         default :
   1188             break;
   1189         }
   1190         break;
   1191     case STANDALONE :
   1192         switch (width) {
   1193         case WIDE :
   1194             if (fStandaloneQuarters)
   1195                 delete[] fStandaloneQuarters;
   1196             fStandaloneQuarters = newUnicodeStringArray(count);
   1197             uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
   1198             fStandaloneQuartersCount = count;
   1199             break;
   1200         case ABBREVIATED :
   1201             if (fStandaloneShortQuarters)
   1202                 delete[] fStandaloneShortQuarters;
   1203             fStandaloneShortQuarters = newUnicodeStringArray(count);
   1204             uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
   1205             fStandaloneShortQuartersCount = count;
   1206             break;
   1207         case NARROW :
   1208         /*
   1209            if (fStandaloneNarrowQuarters)
   1210                 delete[] fStandaloneNarrowQuarters;
   1211             fStandaloneNarrowQuarters = newUnicodeStringArray(count);
   1212             uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
   1213             fStandaloneNarrowQuartersCount = count;
   1214         */
   1215             break;
   1216         default :
   1217             break;
   1218         }
   1219         break;
   1220     case DT_CONTEXT_COUNT :
   1221         break;
   1222     }
   1223 }
   1224 
   1225 void
   1226 DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
   1227 {
   1228     // delete the old list if we own it
   1229     if (fAmPms) delete[] fAmPms;
   1230 
   1231     // we always own the new list, which we create here (we duplicate rather
   1232     // than adopting the list passed in)
   1233     fAmPms = newUnicodeStringArray(count);
   1234     uprv_arrayCopy(amPmsArray,fAmPms,count);
   1235     fAmPmsCount = count;
   1236 }
   1237 
   1238 void
   1239 DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
   1240 {
   1241     fTimeSeparator = newTimeSeparator;
   1242 }
   1243 
   1244 const UnicodeString**
   1245 DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
   1246 {
   1247     const UnicodeString **result = NULL;
   1248 
   1249     umtx_lock(&LOCK);
   1250     if (fZoneStrings == NULL) {
   1251         if (fLocaleZoneStrings == NULL) {
   1252             ((DateFormatSymbols*)this)->initZoneStringsArray();
   1253         }
   1254         result = (const UnicodeString**)fLocaleZoneStrings;
   1255     } else {
   1256         result = (const UnicodeString**)fZoneStrings;
   1257     }
   1258     rowCount = fZoneStringsRowCount;
   1259     columnCount = fZoneStringsColCount;
   1260     umtx_unlock(&LOCK);
   1261 
   1262     return result;
   1263 }
   1264 
   1265 // For now, we include all zones
   1266 #define ZONE_SET UCAL_ZONE_TYPE_ANY
   1267 
   1268 // This code must be called within a synchronized block
   1269 void
   1270 DateFormatSymbols::initZoneStringsArray(void) {
   1271     if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
   1272         return;
   1273     }
   1274 
   1275     UErrorCode status = U_ZERO_ERROR;
   1276 
   1277     StringEnumeration *tzids = NULL;
   1278     UnicodeString ** zarray = NULL;
   1279     TimeZoneNames *tzNames = NULL;
   1280     int32_t rows = 0;
   1281 
   1282     static const UTimeZoneNameType TYPES[] = {
   1283         UTZNM_LONG_STANDARD, UTZNM_SHORT_STANDARD,
   1284         UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_DAYLIGHT
   1285     };
   1286     static const int32_t NUM_TYPES = 4;
   1287 
   1288     do { // dummy do-while
   1289 
   1290         tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
   1291         rows = tzids->count(status);
   1292         if (U_FAILURE(status)) {
   1293             break;
   1294         }
   1295 
   1296         // Allocate array
   1297         int32_t size = rows * sizeof(UnicodeString*);
   1298         zarray = (UnicodeString**)uprv_malloc(size);
   1299         if (zarray == NULL) {
   1300             status = U_MEMORY_ALLOCATION_ERROR;
   1301             break;
   1302         }
   1303         uprv_memset(zarray, 0, size);
   1304 
   1305         tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
   1306         tzNames->loadAllDisplayNames(status);
   1307         if (U_FAILURE(status)) { break; }
   1308 
   1309         const UnicodeString *tzid;
   1310         int32_t i = 0;
   1311         UDate now = Calendar::getNow();
   1312         UnicodeString tzDispName;
   1313 
   1314         while ((tzid = tzids->snext(status))) {
   1315             if (U_FAILURE(status)) {
   1316                 break;
   1317             }
   1318 
   1319             zarray[i] = new UnicodeString[5];
   1320             if (zarray[i] == NULL) {
   1321                 status = U_MEMORY_ALLOCATION_ERROR;
   1322                 break;
   1323             }
   1324 
   1325             zarray[i][0].setTo(*tzid);
   1326             tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
   1327             i++;
   1328         }
   1329 
   1330     } while (FALSE);
   1331 
   1332     if (U_FAILURE(status)) {
   1333         if (zarray) {
   1334             for (int32_t i = 0; i < rows; i++) {
   1335                 if (zarray[i]) {
   1336                     delete[] zarray[i];
   1337                 }
   1338             }
   1339             uprv_free(zarray);
   1340             zarray = NULL;
   1341         }
   1342     }
   1343 
   1344     if (tzNames) {
   1345         delete tzNames;
   1346     }
   1347     if (tzids) {
   1348         delete tzids;
   1349     }
   1350 
   1351     fLocaleZoneStrings = zarray;
   1352     fZoneStringsRowCount = rows;
   1353     fZoneStringsColCount = 1 + NUM_TYPES;
   1354 }
   1355 
   1356 void
   1357 DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
   1358 {
   1359     // since deleting a 2-d array is a pain in the butt, we offload that task to
   1360     // a separate function
   1361     disposeZoneStrings();
   1362     // we always own the new list, which we create here (we duplicate rather
   1363     // than adopting the list passed in)
   1364     fZoneStringsRowCount = rowCount;
   1365     fZoneStringsColCount = columnCount;
   1366     createZoneStrings((const UnicodeString**)strings);
   1367 }
   1368 
   1369 //------------------------------------------------------
   1370 
   1371 const char16_t * U_EXPORT2
   1372 DateFormatSymbols::getPatternUChars(void)
   1373 {
   1374     return gPatternChars;
   1375 }
   1376 
   1377 UDateFormatField U_EXPORT2
   1378 DateFormatSymbols::getPatternCharIndex(UChar c) {
   1379     const UChar *p = u_strchr(gPatternChars, c);
   1380     if (p == NULL) {
   1381         return UDAT_FIELD_COUNT;
   1382     } else {
   1383         return static_cast<UDateFormatField>(p - gPatternChars);
   1384     }
   1385 }
   1386 
   1387 static const uint64_t kNumericFieldsAlways =
   1388     ((uint64_t)1 << UDAT_YEAR_FIELD) |                      // y
   1389     ((uint64_t)1 << UDAT_DATE_FIELD) |                      // d
   1390     ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) |              // k
   1391     ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) |              // H
   1392     ((uint64_t)1 << UDAT_MINUTE_FIELD) |                    // m
   1393     ((uint64_t)1 << UDAT_SECOND_FIELD) |                    // s
   1394     ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) |         // S
   1395     ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) |               // D
   1396     ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) |      // F
   1397     ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) |              // w
   1398     ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) |             // W
   1399     ((uint64_t)1 << UDAT_HOUR1_FIELD) |                     // h
   1400     ((uint64_t)1 << UDAT_HOUR0_FIELD) |                     // K
   1401     ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) |                  // Y
   1402     ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) |             // u
   1403     ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) |                // g
   1404     ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) |       // A
   1405     ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD);               // r
   1406 
   1407 static const uint64_t kNumericFieldsForCount12 =
   1408     ((uint64_t)1 << UDAT_MONTH_FIELD) |                     // M or MM
   1409     ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) |                 // e or ee
   1410     ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) |            // c or cc
   1411     ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) |          // L or LL
   1412     ((uint64_t)1 << UDAT_QUARTER_FIELD) |                   // Q or QQ
   1413     ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD);         // q or qq
   1414 
   1415 UBool U_EXPORT2
   1416 DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
   1417     if (f == UDAT_FIELD_COUNT) {
   1418         return FALSE;
   1419     }
   1420     uint64_t flag = ((uint64_t)1 << f);
   1421     return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
   1422 }
   1423 
   1424 UBool U_EXPORT2
   1425 DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
   1426     return isNumericField(getPatternCharIndex(c), count);
   1427 }
   1428 
   1429 //------------------------------------------------------
   1430 
   1431 UnicodeString&
   1432 DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
   1433 {
   1434     // fastCopyFrom() - see assignArray comments
   1435     return result.fastCopyFrom(fLocalPatternChars);
   1436 }
   1437 
   1438 //------------------------------------------------------
   1439 
   1440 void
   1441 DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
   1442 {
   1443     fLocalPatternChars = newLocalPatternChars;
   1444 }
   1445 
   1446 //------------------------------------------------------
   1447 
   1448 namespace {
   1449 
   1450 // Constants declarations
   1451 static const UChar kCalendarAliasPrefixUChar[] = {
   1452     SOLIDUS, CAP_L, CAP_O, CAP_C, CAP_A, CAP_L, CAP_E, SOLIDUS,
   1453     LOW_C, LOW_A, LOW_L, LOW_E, LOW_N, LOW_D, LOW_A, LOW_R, SOLIDUS
   1454 };
   1455 static const UChar kGregorianTagUChar[] = {
   1456     LOW_G, LOW_R, LOW_E, LOW_G, LOW_O, LOW_R, LOW_I, LOW_A, LOW_N
   1457 };
   1458 static const UChar kVariantTagUChar[] = {
   1459     PERCENT, LOW_V, LOW_A, LOW_R, LOW_I, LOW_A, LOW_N, LOW_T
   1460 };
   1461 static const UChar kLeapTagUChar[] = {
   1462     LOW_L, LOW_E, LOW_A, LOW_P
   1463 };
   1464 static const UChar kCyclicNameSetsTagUChar[] = {
   1465     LOW_C, LOW_Y, LOW_C, LOW_L, LOW_I, LOW_C, CAP_N, LOW_A, LOW_M, LOW_E, CAP_S, LOW_E, LOW_T, LOW_S
   1466 };
   1467 static const UChar kYearsTagUChar[] = {
   1468     SOLIDUS, LOW_Y, LOW_E, LOW_A, LOW_R, LOW_S
   1469 };
   1470 static const UChar kZodiacsUChar[] = {
   1471     SOLIDUS, LOW_Z, LOW_O, LOW_D, LOW_I, LOW_A, LOW_C, LOW_S
   1472 };
   1473 static const UChar kDayPartsTagUChar[] = {
   1474     SOLIDUS, LOW_D, LOW_A, LOW_Y, CAP_P, LOW_A, LOW_R, LOW_T, LOW_S
   1475 };
   1476 static const UChar kFormatTagUChar[] = {
   1477     SOLIDUS, LOW_F, LOW_O, LOW_R, LOW_M, LOW_A, LOW_T
   1478 };
   1479 static const UChar kAbbrTagUChar[] = {
   1480     SOLIDUS, LOW_A, LOW_B, LOW_B, LOW_R, LOW_E, LOW_V, LOW_I, LOW_A, LOW_T, LOW_E, LOW_D
   1481 };
   1482 
   1483 // ResourceSink to enumerate all calendar resources
   1484 struct CalendarDataSink : public ResourceSink {
   1485 
   1486     // Enum which specifies the type of alias received, or no alias
   1487     enum AliasType {
   1488         SAME_CALENDAR,
   1489         DIFFERENT_CALENDAR,
   1490         GREGORIAN,
   1491         NONE
   1492     };
   1493 
   1494     // Data structures to store resources from the current resource bundle
   1495     Hashtable arrays;
   1496     Hashtable arraySizes;
   1497     Hashtable maps;
   1498     /**
   1499      * Whenever there are aliases, the same object will be added twice to 'map'.
   1500      * To avoid double deletion, 'maps' won't take ownership of the objects. Instead,
   1501      * 'mapRefs' will own them and will delete them when CalendarDataSink is deleted.
   1502      */
   1503     UVector mapRefs;
   1504 
   1505     // Paths and the aliases they point to
   1506     UVector aliasPathPairs;
   1507 
   1508     // Current and next calendar resource table which should be loaded
   1509     UnicodeString currentCalendarType;
   1510     UnicodeString nextCalendarType;
   1511 
   1512     // Resources to visit when enumerating fallback calendars
   1513     LocalPointer<UVector> resourcesToVisit;
   1514 
   1515     // Alias' relative path populated whenever an alias is read
   1516     UnicodeString aliasRelativePath;
   1517 
   1518     // Initializes CalendarDataSink with default values
   1519     CalendarDataSink(UErrorCode& status)
   1520     :   arrays(FALSE, status), arraySizes(FALSE, status), maps(FALSE, status),
   1521         mapRefs(deleteHashtable, NULL, 10, status),
   1522         aliasPathPairs(uprv_deleteUObject, uhash_compareUnicodeString, status),
   1523         currentCalendarType(), nextCalendarType(),
   1524         resourcesToVisit(NULL), aliasRelativePath() {
   1525         if (U_FAILURE(status)) { return; }
   1526     }
   1527     virtual ~CalendarDataSink();
   1528 
   1529     // Configure the CalendarSink to visit all the resources
   1530     void visitAllResources() {
   1531         resourcesToVisit.adoptInstead(NULL);
   1532     }
   1533 
   1534     // Actions to be done before enumerating
   1535     void preEnumerate(const UnicodeString &calendarType) {
   1536         currentCalendarType = calendarType;
   1537         nextCalendarType.setToBogus();
   1538         aliasPathPairs.removeAllElements();
   1539     }
   1540 
   1541     virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
   1542         if (U_FAILURE(errorCode)) { return; }
   1543         U_ASSERT(!currentCalendarType.isEmpty());
   1544 
   1545         // Stores the resources to visit on the next calendar.
   1546         LocalPointer<UVector> resourcesToVisitNext(NULL);
   1547         ResourceTable calendarData = value.getTable(errorCode);
   1548         if (U_FAILURE(errorCode)) { return; }
   1549 
   1550         // Enumerate all resources for this calendar
   1551         for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
   1552             UnicodeString keyUString(key, -1, US_INV);
   1553 
   1554             // == Handle aliases ==
   1555             AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
   1556             if (U_FAILURE(errorCode)) { return; }
   1557             if (aliasType == GREGORIAN) {
   1558                 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
   1559                 continue;
   1560 
   1561             } else if (aliasType == DIFFERENT_CALENDAR) {
   1562                 // Whenever an alias to the next calendar (except gregorian) is encountered, register the
   1563                 // calendar type it's pointing to
   1564                 if (resourcesToVisitNext.isNull()) {
   1565                     resourcesToVisitNext
   1566                         .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, errorCode),
   1567                                                        errorCode);
   1568                     if (U_FAILURE(errorCode)) { return; }
   1569                 }
   1570                 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
   1571                 resourcesToVisitNext->addElement(aliasRelativePathCopy.getAlias(), errorCode);
   1572                 if (U_FAILURE(errorCode)) { return; }
   1573                 // Only release ownership after resourcesToVisitNext takes it (no error happened):
   1574                 aliasRelativePathCopy.orphan();
   1575                 continue;
   1576 
   1577             } else if (aliasType == SAME_CALENDAR) {
   1578                 // Register same-calendar alias
   1579                 if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) {
   1580                     LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
   1581                     aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
   1582                     if (U_FAILURE(errorCode)) { return; }
   1583                     // Only release ownership after aliasPathPairs takes it (no error happened):
   1584                     aliasRelativePathCopy.orphan();
   1585                     LocalPointer<UnicodeString> keyUStringCopy(new UnicodeString(keyUString), errorCode);
   1586                     aliasPathPairs.addElement(keyUStringCopy.getAlias(), errorCode);
   1587                     if (U_FAILURE(errorCode)) { return; }
   1588                     // Only release ownership after aliasPathPairs takes it (no error happened):
   1589                     keyUStringCopy.orphan();
   1590                 }
   1591                 continue;
   1592             }
   1593 
   1594             // Only visit the resources that were referenced by an alias on the previous calendar
   1595             // (AmPmMarkersAbbr is an exception).
   1596             if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
   1597                 && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
   1598 
   1599             // == Handle data ==
   1600             if (uprv_strcmp(key, gAmPmMarkersTag) == 0
   1601                 || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
   1602                 || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
   1603                 if (arrays.get(keyUString) == NULL) {
   1604                     ResourceArray resourceArray = value.getArray(errorCode);
   1605                     int32_t arraySize = resourceArray.getSize();
   1606                     LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
   1607                     value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
   1608                     arrays.put(keyUString, stringArray.orphan(), errorCode);
   1609                     arraySizes.puti(keyUString, arraySize, errorCode);
   1610                     if (U_FAILURE(errorCode)) { return; }
   1611                 }
   1612             } else if (uprv_strcmp(key, gErasTag) == 0
   1613                        || uprv_strcmp(key, gDayNamesTag) == 0
   1614                        || uprv_strcmp(key, gMonthNamesTag) == 0
   1615                        || uprv_strcmp(key, gQuartersTag) == 0
   1616                        || uprv_strcmp(key, gDayPeriodTag) == 0
   1617                        || uprv_strcmp(key, gMonthPatternsTag) == 0
   1618                        || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
   1619                 processResource(keyUString, key, value, errorCode);
   1620             }
   1621         }
   1622 
   1623         // Apply same-calendar aliases
   1624         UBool modified;
   1625         do {
   1626             modified = false;
   1627             for (int32_t i = 0; i < aliasPathPairs.size();) {
   1628                 UBool mod = false;
   1629                 UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
   1630                 UnicodeString *aliasArray;
   1631                 Hashtable *aliasMap;
   1632                 if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != NULL) {
   1633                     UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
   1634                     if (arrays.get(*path) == NULL) {
   1635                         // Clone the array
   1636                         int32_t aliasArraySize = arraySizes.geti(*alias);
   1637                         LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
   1638                         if (U_FAILURE(errorCode)) { return; }
   1639                         uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
   1640                         // Put the array on the 'arrays' map
   1641                         arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
   1642                         arraySizes.puti(*path, aliasArraySize, errorCode);
   1643                     }
   1644                     if (U_FAILURE(errorCode)) { return; }
   1645                     mod = true;
   1646                 } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != NULL) {
   1647                     UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
   1648                     if (maps.get(*path) == NULL) {
   1649                         maps.put(*path, aliasMap, errorCode);
   1650                     }
   1651                     if (U_FAILURE(errorCode)) { return; }
   1652                     mod = true;
   1653                 }
   1654                 if (mod) {
   1655                     aliasPathPairs.removeElementAt(i + 1);
   1656                     aliasPathPairs.removeElementAt(i);
   1657                     modified = true;
   1658                 } else {
   1659                     i += 2;
   1660                 }
   1661             }
   1662         } while (modified && !aliasPathPairs.isEmpty());
   1663 
   1664         // Set the resources to visit on the next calendar
   1665         if (!resourcesToVisitNext.isNull()) {
   1666             resourcesToVisit.moveFrom(resourcesToVisitNext);
   1667         }
   1668     }
   1669 
   1670     // Process the nested resource bundle tables
   1671     void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
   1672         if (U_FAILURE(errorCode)) return;
   1673 
   1674         ResourceTable table = value.getTable(errorCode);
   1675         if (U_FAILURE(errorCode)) return;
   1676         Hashtable* stringMap = NULL;
   1677 
   1678         // Iterate over all the elements of the table and add them to the map
   1679         for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
   1680             UnicodeString keyUString(key, -1, US_INV);
   1681 
   1682             // Ignore '%variant' keys
   1683             if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
   1684                 continue;
   1685             }
   1686 
   1687             // == Handle String elements ==
   1688             if (value.getType() == URES_STRING) {
   1689                 // We are on a leaf, store the map elements into the stringMap
   1690                 if (i == 0) {
   1691                     LocalPointer<Hashtable> stringMapPtr(new Hashtable(FALSE, errorCode), errorCode);
   1692                     stringMap = stringMapPtr.getAlias();
   1693                     maps.put(path, stringMap, errorCode);
   1694                     // mapRefs will take ownership of 'stringMap':
   1695                     mapRefs.addElement(stringMap, errorCode);
   1696                     if (U_FAILURE(errorCode)) { return; }
   1697                     // Only release ownership after mapRefs takes it (no error happened):
   1698                     stringMapPtr.orphan();
   1699                     stringMap->setValueDeleter(uprv_deleteUObject);
   1700                 }
   1701                 U_ASSERT(stringMap != NULL);
   1702                 int32_t valueStringSize;
   1703                 const UChar *valueString = value.getString(valueStringSize, errorCode);
   1704                 if (U_FAILURE(errorCode)) { return; }
   1705                 LocalPointer<UnicodeString> valueUString(new UnicodeString(TRUE, valueString, valueStringSize), errorCode);
   1706                 stringMap->put(keyUString, valueUString.orphan(), errorCode);
   1707                 if (U_FAILURE(errorCode)) { return; }
   1708                 continue;
   1709             }
   1710             U_ASSERT(stringMap == NULL);
   1711 
   1712             // Store the current path's length and append the current key to the path.
   1713             int32_t pathLength = path.length();
   1714             path.append(SOLIDUS).append(keyUString);
   1715 
   1716             // In cyclicNameSets ignore everything but years/format/abbreviated
   1717             // and zodiacs/format/abbreviated
   1718             if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
   1719                 UBool skip = TRUE;
   1720                 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
   1721                 int32_t length = 0;
   1722                 if (startIndex == path.length()
   1723                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
   1724                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
   1725                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
   1726                     startIndex += length;
   1727                     length = 0;
   1728                     if (startIndex == path.length()
   1729                         || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
   1730                         startIndex += length;
   1731                         length = 0;
   1732                         if (startIndex == path.length()
   1733                             || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
   1734                             skip = FALSE;
   1735                         }
   1736                     }
   1737                 }
   1738                 if (skip) {
   1739                     // Drop the latest key on the path and continue
   1740                     path.retainBetween(0, pathLength);
   1741                     continue;
   1742                 }
   1743             }
   1744 
   1745             // == Handle aliases ==
   1746             if (arrays.get(path) != NULL || maps.get(path) != NULL) {
   1747                 // Drop the latest key on the path and continue
   1748                 path.retainBetween(0, pathLength);
   1749                 continue;
   1750             }
   1751 
   1752             AliasType aliasType = processAliasFromValue(path, value, errorCode);
   1753             if (U_FAILURE(errorCode)) { return; }
   1754             if (aliasType == SAME_CALENDAR) {
   1755                 // Store the alias path and the current path on aliasPathPairs
   1756                 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
   1757                 aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
   1758                 if (U_FAILURE(errorCode)) { return; }
   1759                 // Only release ownership after aliasPathPairs takes it (no error happened):
   1760                 aliasRelativePathCopy.orphan();
   1761                 LocalPointer<UnicodeString> pathCopy(new UnicodeString(path), errorCode);
   1762                 aliasPathPairs.addElement(pathCopy.getAlias(), errorCode);
   1763                 if (U_FAILURE(errorCode)) { return; }
   1764                 // Only release ownership after aliasPathPairs takes it (no error happened):
   1765                 pathCopy.orphan();
   1766 
   1767                 // Drop the latest key on the path and continue
   1768                 path.retainBetween(0, pathLength);
   1769                 continue;
   1770             }
   1771             U_ASSERT(aliasType == NONE);
   1772 
   1773             // == Handle data ==
   1774             if (value.getType() == URES_ARRAY) {
   1775                 // We are on a leaf, store the array
   1776                 ResourceArray rDataArray = value.getArray(errorCode);
   1777                 int32_t dataArraySize = rDataArray.getSize();
   1778                 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
   1779                 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
   1780                 arrays.put(path, dataArray.orphan(), errorCode);
   1781                 arraySizes.puti(path, dataArraySize, errorCode);
   1782                 if (U_FAILURE(errorCode)) { return; }
   1783             } else if (value.getType() == URES_TABLE) {
   1784                 // We are not on a leaf, recursively process the subtable.
   1785                 processResource(path, key, value, errorCode);
   1786                 if (U_FAILURE(errorCode)) { return; }
   1787             }
   1788 
   1789             // Drop the latest key on the path
   1790             path.retainBetween(0, pathLength);
   1791         }
   1792     }
   1793 
   1794     // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
   1795     AliasType processAliasFromValue(UnicodeString &currentRelativePath, ResourceValue &value,
   1796                                     UErrorCode &errorCode) {
   1797         if (U_FAILURE(errorCode)) { return NONE; }
   1798 
   1799         if (value.getType() == URES_ALIAS) {
   1800             int32_t aliasPathSize;
   1801             const UChar* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
   1802             if (U_FAILURE(errorCode)) { return NONE; }
   1803             UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
   1804             const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
   1805             if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
   1806                 && aliasPath.length() > aliasPrefixLength) {
   1807                 int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
   1808                 if (typeLimit > aliasPrefixLength) {
   1809                     const UnicodeString aliasCalendarType =
   1810                         aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
   1811                     aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
   1812 
   1813                     if (currentCalendarType == aliasCalendarType
   1814                         && currentRelativePath != aliasRelativePath) {
   1815                         // If we have an alias to the same calendar, the path to the resource must be different
   1816                         return SAME_CALENDAR;
   1817 
   1818                     } else if (currentCalendarType != aliasCalendarType
   1819                                && currentRelativePath == aliasRelativePath) {
   1820                         // If we have an alias to a different calendar, the path to the resource must be the same
   1821                         if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
   1822                             return GREGORIAN;
   1823                         } else if (nextCalendarType.isBogus()) {
   1824                             nextCalendarType = aliasCalendarType;
   1825                             return DIFFERENT_CALENDAR;
   1826                         } else if (nextCalendarType == aliasCalendarType) {
   1827                             return DIFFERENT_CALENDAR;
   1828                         }
   1829                     }
   1830                 }
   1831             }
   1832             errorCode = U_INTERNAL_PROGRAM_ERROR;
   1833             return NONE;
   1834         }
   1835         return NONE;
   1836     }
   1837 
   1838     // Deleter function to be used by 'arrays'
   1839     static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
   1840         delete[] static_cast<UnicodeString *>(uArray);
   1841     }
   1842 
   1843     // Deleter function to be used by 'maps'
   1844     static void U_CALLCONV deleteHashtable(void *table) {
   1845         delete static_cast<Hashtable *>(table);
   1846     }
   1847 };
   1848 // Virtual destructors have to be defined out of line
   1849 CalendarDataSink::~CalendarDataSink() {
   1850     arrays.setValueDeleter(deleteUnicodeStringArray);
   1851 }
   1852 }
   1853 
   1854 //------------------------------------------------------
   1855 
   1856 static void
   1857 initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
   1858     if (U_SUCCESS(status)) {
   1859         length = numStr;
   1860         *field = newUnicodeStringArray((size_t)numStr);
   1861         if (*field) {
   1862             for(int32_t i = 0; i<length; i++) {
   1863                 // readonly aliases - all "data" strings are constant
   1864                 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
   1865                 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
   1866             }
   1867         }
   1868         else {
   1869             length = 0;
   1870             status = U_MEMORY_ALLOCATION_ERROR;
   1871         }
   1872     }
   1873 }
   1874 
   1875 static void
   1876 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
   1877     if (U_SUCCESS(status)) {
   1878         UnicodeString keyUString(key.data(), -1, US_INV);
   1879         UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
   1880 
   1881         if (array != NULL) {
   1882             length = sink.arraySizes.geti(keyUString);
   1883             *field = array;
   1884             // DateFormatSymbols takes ownership of the array:
   1885             sink.arrays.remove(keyUString);
   1886         } else {
   1887             length = 0;
   1888             status = U_MISSING_RESOURCE_ERROR;
   1889         }
   1890     }
   1891 }
   1892 
   1893 static void
   1894 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
   1895     if (U_SUCCESS(status)) {
   1896         UnicodeString keyUString(key.data(), -1, US_INV);
   1897         UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
   1898 
   1899         if (array != NULL) {
   1900             int32_t arrayLength = sink.arraySizes.geti(keyUString);
   1901             length = arrayLength + arrayOffset;
   1902             *field = new UnicodeString[length];
   1903             if (*field == NULL) {
   1904                 status = U_MEMORY_ALLOCATION_ERROR;
   1905                 return;
   1906             }
   1907             uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
   1908         } else {
   1909             length = 0;
   1910             status = U_MISSING_RESOURCE_ERROR;
   1911         }
   1912     }
   1913 }
   1914 
   1915 static void
   1916 initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
   1917     field[index].remove();
   1918     if (U_SUCCESS(status)) {
   1919         UnicodeString pathUString(path.data(), -1, US_INV);
   1920         Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
   1921         if (leapMonthTable != NULL) {
   1922             UnicodeString leapLabel(FALSE, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
   1923             UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
   1924             if (leapMonthPattern != NULL) {
   1925                 field[index].fastCopyFrom(*leapMonthPattern);
   1926             } else {
   1927                 field[index].setToBogus();
   1928             }
   1929             return;
   1930         }
   1931         status = U_MISSING_RESOURCE_ERROR;
   1932     }
   1933 }
   1934 
   1935 static CharString
   1936 &buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
   1937     return path.clear().append(segment1, -1, errorCode);
   1938 }
   1939 
   1940 static CharString
   1941 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
   1942                    UErrorCode &errorCode) {
   1943     return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
   1944                                                        .append(segment2, -1, errorCode);
   1945 }
   1946 
   1947 static CharString
   1948 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
   1949                    const char* segment3, UErrorCode &errorCode) {
   1950     return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
   1951                                                                  .append(segment3, -1, errorCode);
   1952 }
   1953 
   1954 static CharString
   1955 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
   1956                    const char* segment3, const char* segment4, UErrorCode &errorCode) {
   1957     return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
   1958                                                                            .append(segment4, -1, errorCode);
   1959 }
   1960 
   1961 typedef struct {
   1962     const char * usageTypeName;
   1963     DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
   1964 } ContextUsageTypeNameToEnumValue;
   1965 
   1966 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
   1967    // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
   1968     { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
   1969     { "day-narrow",     DateFormatSymbols::kCapContextUsageDayNarrow },
   1970     { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
   1971     { "era-abbr",       DateFormatSymbols::kCapContextUsageEraAbbrev },
   1972     { "era-name",       DateFormatSymbols::kCapContextUsageEraWide },
   1973     { "era-narrow",     DateFormatSymbols::kCapContextUsageEraNarrow },
   1974     { "metazone-long",  DateFormatSymbols::kCapContextUsageMetazoneLong },
   1975     { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
   1976     { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
   1977     { "month-narrow",   DateFormatSymbols::kCapContextUsageMonthNarrow },
   1978     { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
   1979     { "zone-long",      DateFormatSymbols::kCapContextUsageZoneLong },
   1980     { "zone-short",     DateFormatSymbols::kCapContextUsageZoneShort },
   1981     { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
   1982 };
   1983 
   1984 // Resource keys to look up localized strings for day periods.
   1985 // The first one must be midnight and the second must be noon, so that their indices coincide
   1986 // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
   1987 static const char *dayPeriodKeys[] = {"midnight", "noon",
   1988                          "morning1", "afternoon1", "evening1", "night1",
   1989                          "morning2", "afternoon2", "evening2", "night2"};
   1990 
   1991 UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
   1992                                     int32_t &stringCount,  UErrorCode &status) {
   1993     if (U_FAILURE(status)) { return NULL; }
   1994 
   1995     UnicodeString pathUString(path.data(), -1, US_INV);
   1996     Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
   1997 
   1998     stringCount = UPRV_LENGTHOF(dayPeriodKeys);
   1999     UnicodeString *strings = new UnicodeString[stringCount];
   2000     if (strings == NULL) {
   2001         status = U_MEMORY_ALLOCATION_ERROR;
   2002         return NULL;
   2003     }
   2004 
   2005     if (map != NULL) {
   2006         for (int32_t i = 0; i < stringCount; ++i) {
   2007             UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
   2008             UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
   2009             if (dayPeriod != NULL) {
   2010                 strings[i].fastCopyFrom(*dayPeriod);
   2011             } else {
   2012                 strings[i].setToBogus();
   2013             }
   2014         }
   2015     } else {
   2016         for (int32_t i = 0; i < stringCount; i++) {
   2017             strings[i].setToBogus();
   2018         }
   2019     }
   2020     return strings;
   2021 }
   2022 
   2023 
   2024 void
   2025 DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
   2026 {
   2027     int32_t len = 0;
   2028     /* In case something goes wrong, initialize all of the data to NULL. */
   2029     fEras = NULL;
   2030     fErasCount = 0;
   2031     fEraNames = NULL;
   2032     fEraNamesCount = 0;
   2033     fNarrowEras = NULL;
   2034     fNarrowErasCount = 0;
   2035     fMonths = NULL;
   2036     fMonthsCount=0;
   2037     fShortMonths = NULL;
   2038     fShortMonthsCount=0;
   2039     fNarrowMonths = NULL;
   2040     fNarrowMonthsCount=0;
   2041     fStandaloneMonths = NULL;
   2042     fStandaloneMonthsCount=0;
   2043     fStandaloneShortMonths = NULL;
   2044     fStandaloneShortMonthsCount=0;
   2045     fStandaloneNarrowMonths = NULL;
   2046     fStandaloneNarrowMonthsCount=0;
   2047     fWeekdays = NULL;
   2048     fWeekdaysCount=0;
   2049     fShortWeekdays = NULL;
   2050     fShortWeekdaysCount=0;
   2051     fShorterWeekdays = NULL;
   2052     fShorterWeekdaysCount=0;
   2053     fNarrowWeekdays = NULL;
   2054     fNarrowWeekdaysCount=0;
   2055     fStandaloneWeekdays = NULL;
   2056     fStandaloneWeekdaysCount=0;
   2057     fStandaloneShortWeekdays = NULL;
   2058     fStandaloneShortWeekdaysCount=0;
   2059     fStandaloneShorterWeekdays = NULL;
   2060     fStandaloneShorterWeekdaysCount=0;
   2061     fStandaloneNarrowWeekdays = NULL;
   2062     fStandaloneNarrowWeekdaysCount=0;
   2063     fAmPms = NULL;
   2064     fAmPmsCount=0;
   2065     fNarrowAmPms = NULL;
   2066     fNarrowAmPmsCount=0;
   2067     fTimeSeparator.setToBogus();
   2068     fQuarters = NULL;
   2069     fQuartersCount = 0;
   2070     fShortQuarters = NULL;
   2071     fShortQuartersCount = 0;
   2072     fStandaloneQuarters = NULL;
   2073     fStandaloneQuartersCount = 0;
   2074     fStandaloneShortQuarters = NULL;
   2075     fStandaloneShortQuartersCount = 0;
   2076     fLeapMonthPatterns = NULL;
   2077     fLeapMonthPatternsCount = 0;
   2078     fShortYearNames = NULL;
   2079     fShortYearNamesCount = 0;
   2080     fShortZodiacNames = NULL;
   2081     fShortZodiacNamesCount = 0;
   2082     fZoneStringsRowCount = 0;
   2083     fZoneStringsColCount = 0;
   2084     fZoneStrings = NULL;
   2085     fLocaleZoneStrings = NULL;
   2086     fAbbreviatedDayPeriods = NULL;
   2087     fAbbreviatedDayPeriodsCount = 0;
   2088     fWideDayPeriods = NULL;
   2089     fWideDayPeriodsCount = 0;
   2090     fNarrowDayPeriods = NULL;
   2091     fNarrowDayPeriodsCount = 0;
   2092     fStandaloneAbbreviatedDayPeriods = NULL;
   2093     fStandaloneAbbreviatedDayPeriodsCount = 0;
   2094     fStandaloneWideDayPeriods = NULL;
   2095     fStandaloneWideDayPeriodsCount = 0;
   2096     fStandaloneNarrowDayPeriods = NULL;
   2097     fStandaloneNarrowDayPeriodsCount = 0;
   2098     uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
   2099 
   2100     // We need to preserve the requested locale for
   2101     // lazy ZoneStringFormat instantiation.  ZoneStringFormat
   2102     // is region sensitive, thus, bundle locale bundle's locale
   2103     // is not sufficient.
   2104     fZSFLocale = locale;
   2105 
   2106     if (U_FAILURE(status)) return;
   2107 
   2108     // Create a CalendarDataSink to process this data and the resouce bundles
   2109     CalendarDataSink calendarSink(status);
   2110     UResourceBundle *rb = ures_open(NULL, locale.getBaseName(), &status);
   2111     UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, NULL, &status);
   2112 
   2113     if (U_FAILURE(status)) return;
   2114 
   2115     // Iterate over the resource bundle data following the fallbacks through different calendar types
   2116     UnicodeString calendarType((type != NULL && *type != '\0')? type : gGregorianTag, -1, US_INV);
   2117     while (!calendarType.isBogus()) {
   2118         CharString calendarTypeBuffer;
   2119         calendarTypeBuffer.appendInvariantChars(calendarType, status);
   2120         if (U_FAILURE(status)) { return; }
   2121         const char *calendarTypeCArray = calendarTypeBuffer.data();
   2122 
   2123         // Enumerate this calendar type. If the calendar is not found fallback to gregorian
   2124         UErrorCode oldStatus = status;
   2125         UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, NULL, &status);
   2126         if (status == U_MISSING_RESOURCE_ERROR) {
   2127             ures_close(ctb);
   2128             if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
   2129                 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
   2130                 calendarSink.visitAllResources();
   2131                 status = oldStatus;
   2132                 continue;
   2133             }
   2134             return;
   2135         }
   2136 
   2137         calendarSink.preEnumerate(calendarType);
   2138         ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
   2139         ures_close(ctb);
   2140         if (U_FAILURE(status)) break;
   2141 
   2142         // Stop loading when gregorian was loaded
   2143         if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
   2144             break;
   2145         }
   2146 
   2147         // Get the next calendar type to process from the sink
   2148         calendarType = calendarSink.nextCalendarType;
   2149 
   2150         // Gregorian is always the last fallback
   2151         if (calendarType.isBogus()) {
   2152             calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
   2153             calendarSink.visitAllResources();
   2154         }
   2155     }
   2156 
   2157     // CharString object to build paths
   2158     CharString path;
   2159 
   2160     // Load Leap Month Patterns
   2161     UErrorCode tempStatus = status;
   2162     fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
   2163     if (fLeapMonthPatterns) {
   2164         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
   2165                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
   2166         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
   2167                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
   2168         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
   2169                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
   2170         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
   2171                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
   2172         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
   2173                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
   2174         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
   2175                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
   2176         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
   2177                              buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
   2178         if (U_SUCCESS(tempStatus)) {
   2179             // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
   2180             // The ordering of the following statements is important.
   2181             if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
   2182                 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
   2183             };
   2184             if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
   2185                 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
   2186             };
   2187             if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
   2188                 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
   2189             };
   2190             if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
   2191                 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
   2192             };
   2193             // end of hack
   2194             fLeapMonthPatternsCount = kMonthPatternsCount;
   2195         } else {
   2196             delete[] fLeapMonthPatterns;
   2197             fLeapMonthPatterns = NULL;
   2198         }
   2199     }
   2200 
   2201     // Load cyclic names sets
   2202     tempStatus = status;
   2203     initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
   2204               buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
   2205     initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
   2206               buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
   2207 
   2208     // Load context transforms and capitalization
   2209     tempStatus = U_ZERO_ERROR;
   2210     UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
   2211     if (U_SUCCESS(tempStatus)) {
   2212         UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
   2213         if (U_SUCCESS(tempStatus)) {
   2214             UResourceBundle *contextTransformUsage;
   2215             while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
   2216                 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
   2217                 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
   2218                     const char* usageType = ures_getKey(contextTransformUsage);
   2219                     if (usageType != NULL) {
   2220                         const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
   2221                         int32_t compResult = 0;
   2222                         // linear search; list is short and we cannot be sure that bsearch is available
   2223                         while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
   2224                             ++typeMapPtr;
   2225                         }
   2226                         if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
   2227                             fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0];
   2228                             fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1];
   2229                         }
   2230                     }
   2231                 }
   2232                 tempStatus = U_ZERO_ERROR;
   2233                 ures_close(contextTransformUsage);
   2234             }
   2235             ures_close(contextTransforms);
   2236         }
   2237 
   2238         tempStatus = U_ZERO_ERROR;
   2239         const LocalPointer<NumberingSystem> numberingSystem(
   2240                 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
   2241         if (U_SUCCESS(tempStatus)) {
   2242             // These functions all fail gracefully if passed NULL pointers and
   2243             // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
   2244             // to check for errors once after all calls are made.
   2245             const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
   2246                     localeBundle, gNumberElementsTag, NULL, &tempStatus));
   2247             const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
   2248                     numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
   2249             const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
   2250                     nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
   2251             fTimeSeparator = ures_getUnicodeStringByKey(
   2252                     symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
   2253             if (U_FAILURE(tempStatus)) {
   2254                 fTimeSeparator.setToBogus();
   2255             }
   2256         }
   2257 
   2258         ures_close(localeBundle);
   2259     }
   2260 
   2261     if (fTimeSeparator.isBogus()) {
   2262         fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
   2263     }
   2264 
   2265     // Load day periods
   2266     fWideDayPeriods = loadDayPeriodStrings(calendarSink,
   2267                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
   2268                             fWideDayPeriodsCount, status);
   2269     fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
   2270                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
   2271                             fNarrowDayPeriodsCount, status);
   2272     fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
   2273                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
   2274                             fAbbreviatedDayPeriodsCount, status);
   2275     fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
   2276                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
   2277                             fStandaloneWideDayPeriodsCount, status);
   2278     fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
   2279                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
   2280                             fStandaloneNarrowDayPeriodsCount, status);
   2281     fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
   2282                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
   2283                             fStandaloneAbbreviatedDayPeriodsCount, status);
   2284 
   2285     U_LOCALE_BASED(locBased, *this);
   2286     // if we make it to here, the resource data is cool, and we can get everything out
   2287     // of it that we need except for the time-zone and localized-pattern data, which
   2288     // are stored in a separate file
   2289     locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
   2290                           ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
   2291 
   2292     // Load eras
   2293     initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
   2294     UErrorCode oldStatus = status;
   2295     initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
   2296     if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
   2297         status = oldStatus;
   2298         assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
   2299     }
   2300     // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
   2301     oldStatus = status;
   2302     initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
   2303     if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
   2304         status = oldStatus;
   2305         assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
   2306     }
   2307 
   2308     // Load month names
   2309     initField(&fMonths, fMonthsCount, calendarSink,
   2310               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
   2311     initField(&fShortMonths, fShortMonthsCount, calendarSink,
   2312               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
   2313     initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
   2314               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
   2315     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
   2316         status = U_ZERO_ERROR;
   2317         assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
   2318     }
   2319     initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
   2320               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
   2321     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
   2322         status = U_ZERO_ERROR;
   2323         assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
   2324     }
   2325 
   2326     UErrorCode narrowMonthsEC = status;
   2327     UErrorCode standaloneNarrowMonthsEC = status;
   2328     initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
   2329               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
   2330     initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
   2331               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
   2332     if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
   2333         // If format/narrow not available, use standalone/narrow
   2334         assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
   2335     } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
   2336         // If standalone/narrow not availabe, use format/narrow
   2337         assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
   2338     } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
   2339         // If neither is available, use format/abbreviated
   2340         assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
   2341         assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
   2342     }
   2343 
   2344     // Load AM/PM markers
   2345     initField(&fAmPms, fAmPmsCount, calendarSink,
   2346               buildResourcePath(path, gAmPmMarkersTag, status), status);
   2347     initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
   2348               buildResourcePath(path, gAmPmMarkersNarrowTag, status), status);
   2349 
   2350     // Load quarters
   2351     initField(&fQuarters, fQuartersCount, calendarSink,
   2352               buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
   2353     initField(&fShortQuarters, fShortQuartersCount, calendarSink,
   2354               buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
   2355 
   2356     initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
   2357               buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
   2358     if(status == U_MISSING_RESOURCE_ERROR) {
   2359         status = U_ZERO_ERROR;
   2360         assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
   2361     }
   2362     initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
   2363               buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
   2364     if(status == U_MISSING_RESOURCE_ERROR) {
   2365         status = U_ZERO_ERROR;
   2366         assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
   2367     }
   2368 
   2369     // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
   2370     /*
   2371     // fastCopyFrom()/setTo() - see assignArray comments
   2372     resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
   2373     fLocalPatternChars.setTo(TRUE, resStr, len);
   2374     // If the locale data does not include new pattern chars, use the defaults
   2375     // TODO: Consider making this an error, since this may add conflicting characters.
   2376     if (len < PATTERN_CHARS_LEN) {
   2377         fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
   2378     }
   2379     */
   2380     fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
   2381 
   2382     // Format wide weekdays -> fWeekdays
   2383     // {sfb} fixed to handle 1-based weekdays
   2384     initField(&fWeekdays, fWeekdaysCount, calendarSink,
   2385               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
   2386 
   2387     // Format abbreviated weekdays -> fShortWeekdays
   2388     initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
   2389               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
   2390 
   2391     // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
   2392     initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
   2393               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
   2394     if (status == U_MISSING_RESOURCE_ERROR) {
   2395         status = U_ZERO_ERROR;
   2396         assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
   2397     }
   2398 
   2399     // Stand-alone wide weekdays -> fStandaloneWeekdays
   2400     initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
   2401               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
   2402     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
   2403         status = U_ZERO_ERROR;
   2404         assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
   2405     }
   2406 
   2407     // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
   2408     initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
   2409               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
   2410     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
   2411         status = U_ZERO_ERROR;
   2412         assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
   2413     }
   2414 
   2415     // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
   2416     initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
   2417               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
   2418     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
   2419         status = U_ZERO_ERROR;
   2420         assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
   2421     }
   2422 
   2423     // Format narrow weekdays -> fNarrowWeekdays
   2424     UErrorCode narrowWeeksEC = status;
   2425     initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
   2426               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
   2427     // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
   2428     UErrorCode standaloneNarrowWeeksEC = status;
   2429     initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
   2430               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
   2431 
   2432     if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
   2433         // If format/narrow not available, use standalone/narrow
   2434         assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
   2435     } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
   2436         // If standalone/narrow not available, use format/narrow
   2437         assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
   2438     } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
   2439         // If neither is available, use format/abbreviated
   2440         assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
   2441         assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
   2442     }
   2443 
   2444     // Last resort fallback in case previous data wasn't loaded
   2445     if (U_FAILURE(status))
   2446     {
   2447         if (useLastResortData)
   2448         {
   2449             // Handle the case in which there is no resource data present.
   2450             // We don't have to generate usable patterns in this situation;
   2451             // we just need to produce something that will be semi-intelligible
   2452             // in most locales.
   2453 
   2454             status = U_USING_FALLBACK_WARNING;
   2455             //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
   2456             initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
   2457             initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
   2458             initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
   2459             initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
   2460             initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
   2461             initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
   2462             initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
   2463             initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
   2464             initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
   2465             initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2466             initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2467             initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2468             initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2469             initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2470             initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2471             initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2472             initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
   2473             initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
   2474             initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
   2475             initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
   2476             initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
   2477             initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
   2478             initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
   2479             fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
   2480         }
   2481     }
   2482 
   2483     // Close resources
   2484     ures_close(cb);
   2485     ures_close(rb);
   2486 }
   2487 
   2488 Locale
   2489 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
   2490     U_LOCALE_BASED(locBased, *this);
   2491     return locBased.getLocale(type, status);
   2492 }
   2493 
   2494 U_NAMESPACE_END
   2495 
   2496 #endif /* #if !UCONFIG_NO_FORMATTING */
   2497 
   2498 //eof
   2499