LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - dtfmtsym.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1307 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 81 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : SharedDateFormatSymbols::~SharedDateFormatSymbols() {
     170           0 : }
     171             : 
     172             : template<> U_I18N_API
     173             : const SharedDateFormatSymbols *
     174           0 :         LocaleCacheKey<SharedDateFormatSymbols>::createObject(
     175             :                 const void * /*unusedContext*/, UErrorCode &status) const {
     176             :     char type[256];
     177           0 :     Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
     178           0 :     if (U_FAILURE(status)) {
     179           0 :         return NULL;
     180             :     }
     181             :     SharedDateFormatSymbols *shared
     182           0 :             = new SharedDateFormatSymbols(fLoc, type, status);
     183           0 :     if (shared == NULL) {
     184           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     185           0 :         return NULL;
     186             :     }
     187           0 :     if (U_FAILURE(status)) {
     188           0 :         delete shared;
     189           0 :         return NULL;
     190             :     }
     191           0 :     shared->addRef();
     192           0 :     return shared;
     193             : }
     194             : 
     195           0 : 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           0 : static inline UnicodeString* newUnicodeStringArray(size_t count) {
     242           0 :     return new UnicodeString[count ? count : 1];
     243             : }
     244             : 
     245             : //------------------------------------------------------
     246             : 
     247             : DateFormatSymbols * U_EXPORT2
     248           0 : DateFormatSymbols::createForLocale(
     249             :         const Locale& locale, UErrorCode &status) {
     250           0 :     const SharedDateFormatSymbols *shared = NULL;
     251           0 :     UnifiedCache::getByLocale(locale, shared, status);
     252           0 :     if (U_FAILURE(status)) {
     253           0 :         return NULL;
     254             :     }
     255           0 :     DateFormatSymbols *result = new DateFormatSymbols(shared->get());
     256           0 :     shared->removeRef();
     257           0 :     if (result == NULL) {
     258           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     259           0 :         return NULL;
     260             :     }
     261           0 :     return result;
     262             : }
     263             : 
     264           0 : DateFormatSymbols::DateFormatSymbols(const Locale& locale,
     265           0 :                                      UErrorCode& status)
     266           0 :     : UObject()
     267             : {
     268           0 :   initializeData(locale, NULL,  status);
     269           0 : }
     270             : 
     271           0 : DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
     272           0 :     : UObject()
     273             : {
     274           0 :   initializeData(Locale::getDefault(), NULL, status, TRUE);
     275           0 : }
     276             : 
     277             : 
     278           0 : DateFormatSymbols::DateFormatSymbols(const Locale& locale,
     279             :                                      const char *type,
     280           0 :                                      UErrorCode& status)
     281           0 :     : UObject()
     282             : {
     283           0 :   initializeData(locale, type,  status);
     284           0 : }
     285             : 
     286           0 : DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
     287           0 :     : UObject()
     288             : {
     289           0 :   initializeData(Locale::getDefault(), type, status, TRUE);
     290           0 : }
     291             : 
     292           0 : DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
     293           0 :     : UObject(other)
     294             : {
     295           0 :     copyData(other);
     296           0 : }
     297             : 
     298             : void
     299           0 : 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           0 :     dstCount = srcCount;
     317           0 :     dstArray = newUnicodeStringArray(srcCount);
     318           0 :     if(dstArray != NULL) {
     319             :         int32_t i;
     320           0 :         for(i=0; i<srcCount; ++i) {
     321           0 :             dstArray[i].fastCopyFrom(srcArray[i]);
     322             :         }
     323             :     }
     324           0 : }
     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           0 : DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
     333             : {
     334             :     int32_t row, col;
     335           0 :     UBool failed = FALSE;
     336             : 
     337           0 :     fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
     338           0 :     if (fZoneStrings != NULL) {
     339           0 :         for (row=0; row<fZoneStringsRowCount; ++row)
     340             :         {
     341           0 :             fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
     342           0 :             if (fZoneStrings[row] == NULL) {
     343           0 :                 failed = TRUE;
     344           0 :                 break;
     345             :             }
     346           0 :             for (col=0; col<fZoneStringsColCount; ++col) {
     347             :                 // fastCopyFrom() - see assignArray comments
     348           0 :                 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
     349             :             }
     350             :         }
     351             :     }
     352             :     // If memory allocation failed, roll back and delete fZoneStrings
     353           0 :     if (failed) {
     354           0 :         for (int i = row; i >= 0; i--) {
     355           0 :             delete[] fZoneStrings[i];
     356             :         }
     357           0 :         uprv_free(fZoneStrings);
     358           0 :         fZoneStrings = NULL;
     359             :     }
     360           0 : }
     361             : 
     362             : /**
     363             :  * Copy all of the other's data to this.
     364             :  */
     365             : void
     366           0 : DateFormatSymbols::copyData(const DateFormatSymbols& other) {
     367           0 :     UErrorCode status = U_ZERO_ERROR;
     368           0 :     U_LOCALE_BASED(locBased, *this);
     369             :     locBased.setLocaleIDs(
     370           0 :         other.getLocale(ULOC_VALID_LOCALE, status),
     371           0 :         other.getLocale(ULOC_ACTUAL_LOCALE, status));
     372           0 :     assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
     373           0 :     assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
     374           0 :     assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
     375           0 :     assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
     376           0 :     assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
     377           0 :     assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
     378           0 :     assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
     379           0 :     assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
     380           0 :     assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
     381           0 :     assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
     382           0 :     assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
     383           0 :     assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
     384           0 :     assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
     385           0 :     assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
     386           0 :     assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
     387           0 :     assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
     388           0 :     assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
     389           0 :     assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
     390           0 :     assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
     391           0 :     fTimeSeparator.fastCopyFrom(other.fTimeSeparator);  // fastCopyFrom() - see assignArray comments
     392           0 :     assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
     393           0 :     assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
     394           0 :     assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
     395           0 :     assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
     396           0 :     assignArray(fWideDayPeriods, fWideDayPeriodsCount,
     397           0 :                 other.fWideDayPeriods, other.fWideDayPeriodsCount);
     398           0 :     assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
     399           0 :                 other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
     400           0 :     assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
     401           0 :                 other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
     402           0 :     assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
     403           0 :                 other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
     404           0 :     assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
     405           0 :                 other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
     406           0 :     assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
     407           0 :                 other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
     408           0 :     if (other.fLeapMonthPatterns != NULL) {
     409           0 :         assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
     410             :     } else {
     411           0 :         fLeapMonthPatterns = NULL;
     412           0 :         fLeapMonthPatternsCount = 0;
     413             :     }
     414           0 :     if (other.fShortYearNames != NULL) {
     415           0 :         assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
     416             :     } else {
     417           0 :         fShortYearNames = NULL;
     418           0 :         fShortYearNamesCount = 0;
     419             :     }
     420           0 :     if (other.fShortZodiacNames != NULL) {
     421           0 :         assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
     422             :     } else {
     423           0 :         fShortZodiacNames = NULL;
     424           0 :         fShortZodiacNamesCount = 0;
     425             :     }
     426             : 
     427           0 :     if (other.fZoneStrings != NULL) {
     428           0 :         fZoneStringsColCount = other.fZoneStringsColCount;
     429           0 :         fZoneStringsRowCount = other.fZoneStringsRowCount;
     430           0 :         createZoneStrings((const UnicodeString**)other.fZoneStrings);
     431             : 
     432             :     } else {
     433           0 :         fZoneStrings = NULL;
     434           0 :         fZoneStringsColCount = 0;
     435           0 :         fZoneStringsRowCount = 0;
     436             :     }
     437           0 :     fZSFLocale = other.fZSFLocale;
     438             :     // Other zone strings data is created on demand
     439           0 :     fLocaleZoneStrings = NULL;
     440             : 
     441             :     // fastCopyFrom() - see assignArray comments
     442           0 :     fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
     443             : 
     444           0 :     uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
     445           0 : }
     446             : 
     447             : /**
     448             :  * Assignment operator.
     449             :  */
     450           0 : DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
     451             : {
     452           0 :     dispose();
     453           0 :     copyData(other);
     454             : 
     455           0 :     return *this;
     456             : }
     457             : 
     458           0 : DateFormatSymbols::~DateFormatSymbols()
     459             : {
     460           0 :     dispose();
     461           0 : }
     462             : 
     463           0 : void DateFormatSymbols::dispose()
     464             : {
     465           0 :     delete[] fEras;
     466           0 :     delete[] fEraNames;
     467           0 :     delete[] fNarrowEras;
     468           0 :     delete[] fMonths;
     469           0 :     delete[] fShortMonths;
     470           0 :     delete[] fNarrowMonths;
     471           0 :     delete[] fStandaloneMonths;
     472           0 :     delete[] fStandaloneShortMonths;
     473           0 :     delete[] fStandaloneNarrowMonths;
     474           0 :     delete[] fWeekdays;
     475           0 :     delete[] fShortWeekdays;
     476           0 :     delete[] fShorterWeekdays;
     477           0 :     delete[] fNarrowWeekdays;
     478           0 :     delete[] fStandaloneWeekdays;
     479           0 :     delete[] fStandaloneShortWeekdays;
     480           0 :     delete[] fStandaloneShorterWeekdays;
     481           0 :     delete[] fStandaloneNarrowWeekdays;
     482           0 :     delete[] fAmPms;
     483           0 :     delete[] fNarrowAmPms;
     484           0 :     delete[] fQuarters;
     485           0 :     delete[] fShortQuarters;
     486           0 :     delete[] fStandaloneQuarters;
     487           0 :     delete[] fStandaloneShortQuarters;
     488           0 :     delete[] fLeapMonthPatterns;
     489           0 :     delete[] fShortYearNames;
     490           0 :     delete[] fShortZodiacNames;
     491           0 :     delete[] fAbbreviatedDayPeriods;
     492           0 :     delete[] fWideDayPeriods;
     493           0 :     delete[] fNarrowDayPeriods;
     494           0 :     delete[] fStandaloneAbbreviatedDayPeriods;
     495           0 :     delete[] fStandaloneWideDayPeriods;
     496           0 :     delete[] fStandaloneNarrowDayPeriods;
     497             : 
     498           0 :     disposeZoneStrings();
     499           0 : }
     500             : 
     501           0 : void DateFormatSymbols::disposeZoneStrings()
     502             : {
     503           0 :     if (fZoneStrings) {
     504           0 :         for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
     505           0 :             delete[] fZoneStrings[row];
     506             :         }
     507           0 :         uprv_free(fZoneStrings);
     508             :     }
     509           0 :     if (fLocaleZoneStrings) {
     510           0 :         for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
     511           0 :             delete[] fLocaleZoneStrings[row];
     512             :         }
     513           0 :         uprv_free(fLocaleZoneStrings);
     514             :     }
     515             : 
     516           0 :     fZoneStrings = NULL;
     517           0 :     fLocaleZoneStrings = NULL;
     518           0 :     fZoneStringsRowCount = 0;
     519           0 :     fZoneStringsColCount = 0;
     520           0 : }
     521             : 
     522             : UBool
     523           0 : DateFormatSymbols::arrayCompare(const UnicodeString* array1,
     524             :                                 const UnicodeString* array2,
     525             :                                 int32_t count)
     526             : {
     527           0 :     if (array1 == array2) return TRUE;
     528           0 :     while (count>0)
     529             :     {
     530           0 :         --count;
     531           0 :         if (array1[count] != array2[count]) return FALSE;
     532             :     }
     533           0 :     return TRUE;
     534             : }
     535             : 
     536             : UBool
     537           0 : DateFormatSymbols::operator==(const DateFormatSymbols& other) const
     538             : {
     539             :     // First do cheap comparisons
     540           0 :     if (this == &other) {
     541           0 :         return TRUE;
     542             :     }
     543           0 :     if (fErasCount == other.fErasCount &&
     544           0 :         fEraNamesCount == other.fEraNamesCount &&
     545           0 :         fNarrowErasCount == other.fNarrowErasCount &&
     546           0 :         fMonthsCount == other.fMonthsCount &&
     547           0 :         fShortMonthsCount == other.fShortMonthsCount &&
     548           0 :         fNarrowMonthsCount == other.fNarrowMonthsCount &&
     549           0 :         fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
     550           0 :         fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
     551           0 :         fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
     552           0 :         fWeekdaysCount == other.fWeekdaysCount &&
     553           0 :         fShortWeekdaysCount == other.fShortWeekdaysCount &&
     554           0 :         fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
     555           0 :         fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
     556           0 :         fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
     557           0 :         fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
     558           0 :         fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
     559           0 :         fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
     560           0 :         fAmPmsCount == other.fAmPmsCount &&
     561           0 :         fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
     562           0 :         fQuartersCount == other.fQuartersCount &&
     563           0 :         fShortQuartersCount == other.fShortQuartersCount &&
     564           0 :         fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
     565           0 :         fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
     566           0 :         fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
     567           0 :         fShortYearNamesCount == other.fShortYearNamesCount &&
     568           0 :         fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
     569           0 :         fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
     570           0 :         fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
     571           0 :         fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
     572           0 :         fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
     573           0 :         fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
     574           0 :         fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
     575           0 :         (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
     576             :     {
     577             :         // Now compare the arrays themselves
     578           0 :         if (arrayCompare(fEras, other.fEras, fErasCount) &&
     579           0 :             arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
     580           0 :             arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
     581           0 :             arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
     582           0 :             arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
     583           0 :             arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
     584           0 :             arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
     585           0 :             arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
     586           0 :             arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
     587           0 :             arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
     588           0 :             arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
     589           0 :             arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
     590           0 :             arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
     591           0 :             arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
     592           0 :             arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
     593           0 :             arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
     594           0 :             arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
     595           0 :             arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
     596           0 :             arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
     597           0 :             fTimeSeparator == other.fTimeSeparator &&
     598           0 :             arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
     599           0 :             arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
     600           0 :             arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
     601           0 :             arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
     602           0 :             arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
     603           0 :             arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
     604           0 :             arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
     605           0 :             arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
     606           0 :             arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
     607           0 :             arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
     608           0 :             arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
     609           0 :                          fStandaloneAbbreviatedDayPeriodsCount) &&
     610           0 :             arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
     611           0 :                          fStandaloneWideDayPeriodsCount) &&
     612           0 :             arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
     613           0 :                          fStandaloneWideDayPeriodsCount))
     614             :         {
     615             :             // Compare the contents of fZoneStrings
     616           0 :             if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
     617           0 :                 if (fZSFLocale == other.fZSFLocale) {
     618           0 :                     return TRUE;
     619             :                 }
     620           0 :             } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
     621           0 :                 if (fZoneStringsRowCount == other.fZoneStringsRowCount
     622           0 :                     && fZoneStringsColCount == other.fZoneStringsColCount) {
     623           0 :                     UBool cmpres = TRUE;
     624           0 :                     for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
     625           0 :                         cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
     626             :                     }
     627           0 :                     return cmpres;
     628             :                 }
     629             :             }
     630           0 :             return FALSE;
     631             :         }
     632             :     }
     633           0 :     return FALSE;
     634             : }
     635             : 
     636             : //------------------------------------------------------
     637             : 
     638             : const UnicodeString*
     639           0 : DateFormatSymbols::getEras(int32_t &count) const
     640             : {
     641           0 :     count = fErasCount;
     642           0 :     return fEras;
     643             : }
     644             : 
     645             : const UnicodeString*
     646           0 : DateFormatSymbols::getEraNames(int32_t &count) const
     647             : {
     648           0 :     count = fEraNamesCount;
     649           0 :     return fEraNames;
     650             : }
     651             : 
     652             : const UnicodeString*
     653           0 : DateFormatSymbols::getNarrowEras(int32_t &count) const
     654             : {
     655           0 :     count = fNarrowErasCount;
     656           0 :     return fNarrowEras;
     657             : }
     658             : 
     659             : const UnicodeString*
     660           0 : DateFormatSymbols::getMonths(int32_t &count) const
     661             : {
     662           0 :     count = fMonthsCount;
     663           0 :     return fMonths;
     664             : }
     665             : 
     666             : const UnicodeString*
     667           0 : DateFormatSymbols::getShortMonths(int32_t &count) const
     668             : {
     669           0 :     count = fShortMonthsCount;
     670           0 :     return fShortMonths;
     671             : }
     672             : 
     673             : const UnicodeString*
     674           0 : DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
     675             : {
     676           0 :     UnicodeString *returnValue = NULL;
     677             : 
     678           0 :     switch (context) {
     679             :     case FORMAT :
     680           0 :         switch(width) {
     681             :         case WIDE :
     682           0 :             count = fMonthsCount;
     683           0 :             returnValue = fMonths;
     684           0 :             break;
     685             :         case ABBREVIATED :
     686             :         case SHORT : // no month data for this, defaults to ABBREVIATED
     687           0 :             count = fShortMonthsCount;
     688           0 :             returnValue = fShortMonths;
     689           0 :             break;
     690             :         case NARROW :
     691           0 :             count = fNarrowMonthsCount;
     692           0 :             returnValue = fNarrowMonths;
     693           0 :             break;
     694             :         case DT_WIDTH_COUNT :
     695           0 :             break;
     696             :         }
     697           0 :         break;
     698             :     case STANDALONE :
     699           0 :         switch(width) {
     700             :         case WIDE :
     701           0 :             count = fStandaloneMonthsCount;
     702           0 :             returnValue = fStandaloneMonths;
     703           0 :             break;
     704             :         case ABBREVIATED :
     705             :         case SHORT : // no month data for this, defaults to ABBREVIATED
     706           0 :             count = fStandaloneShortMonthsCount;
     707           0 :             returnValue = fStandaloneShortMonths;
     708           0 :             break;
     709             :         case NARROW :
     710           0 :             count = fStandaloneNarrowMonthsCount;
     711           0 :             returnValue = fStandaloneNarrowMonths;
     712           0 :             break;
     713             :         case DT_WIDTH_COUNT :
     714           0 :             break;
     715             :         }
     716           0 :         break;
     717             :     case DT_CONTEXT_COUNT :
     718           0 :         break;
     719             :     }
     720           0 :     return returnValue;
     721             : }
     722             : 
     723             : const UnicodeString*
     724           0 : DateFormatSymbols::getWeekdays(int32_t &count) const
     725             : {
     726           0 :     count = fWeekdaysCount;
     727           0 :     return fWeekdays;
     728             : }
     729             : 
     730             : const UnicodeString*
     731           0 : DateFormatSymbols::getShortWeekdays(int32_t &count) const
     732             : {
     733           0 :     count = fShortWeekdaysCount;
     734           0 :     return fShortWeekdays;
     735             : }
     736             : 
     737             : const UnicodeString*
     738           0 : DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
     739             : {
     740           0 :     UnicodeString *returnValue = NULL;
     741           0 :     switch (context) {
     742             :     case FORMAT :
     743           0 :         switch(width) {
     744             :             case WIDE :
     745           0 :                 count = fWeekdaysCount;
     746           0 :                 returnValue = fWeekdays;
     747           0 :                 break;
     748             :             case ABBREVIATED :
     749           0 :                 count = fShortWeekdaysCount;
     750           0 :                 returnValue = fShortWeekdays;
     751           0 :                 break;
     752             :             case SHORT :
     753           0 :                 count = fShorterWeekdaysCount;
     754           0 :                 returnValue = fShorterWeekdays;
     755           0 :                 break;
     756             :             case NARROW :
     757           0 :                 count = fNarrowWeekdaysCount;
     758           0 :                 returnValue = fNarrowWeekdays;
     759           0 :                 break;
     760             :             case DT_WIDTH_COUNT :
     761           0 :                 break;
     762             :         }
     763           0 :         break;
     764             :     case STANDALONE :
     765           0 :         switch(width) {
     766             :             case WIDE :
     767           0 :                 count = fStandaloneWeekdaysCount;
     768           0 :                 returnValue = fStandaloneWeekdays;
     769           0 :                 break;
     770             :             case ABBREVIATED :
     771           0 :                 count = fStandaloneShortWeekdaysCount;
     772           0 :                 returnValue = fStandaloneShortWeekdays;
     773           0 :                 break;
     774             :             case SHORT :
     775           0 :                 count = fStandaloneShorterWeekdaysCount;
     776           0 :                 returnValue = fStandaloneShorterWeekdays;
     777           0 :                 break;
     778             :             case NARROW :
     779           0 :                 count = fStandaloneNarrowWeekdaysCount;
     780           0 :                 returnValue = fStandaloneNarrowWeekdays;
     781           0 :                 break;
     782             :             case DT_WIDTH_COUNT :
     783           0 :                 break;
     784             :         }
     785           0 :         break;
     786             :     case DT_CONTEXT_COUNT :
     787           0 :         break;
     788             :     }
     789           0 :     return returnValue;
     790             : }
     791             : 
     792             : const UnicodeString*
     793           0 : DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
     794             : {
     795           0 :     UnicodeString *returnValue = NULL;
     796             : 
     797           0 :     switch (context) {
     798             :     case FORMAT :
     799           0 :         switch(width) {
     800             :         case WIDE :
     801           0 :             count = fQuartersCount;
     802           0 :             returnValue = fQuarters;
     803           0 :             break;
     804             :         case ABBREVIATED :
     805             :         case SHORT : // no quarter data for this, defaults to ABBREVIATED
     806           0 :             count = fShortQuartersCount;
     807           0 :             returnValue = fShortQuarters;
     808           0 :             break;
     809             :         case NARROW :
     810           0 :             count = 0;
     811           0 :             returnValue = NULL;
     812           0 :             break;
     813             :         case DT_WIDTH_COUNT :
     814           0 :             break;
     815             :         }
     816           0 :         break;
     817             :     case STANDALONE :
     818           0 :         switch(width) {
     819             :         case WIDE :
     820           0 :             count = fStandaloneQuartersCount;
     821           0 :             returnValue = fStandaloneQuarters;
     822           0 :             break;
     823             :         case ABBREVIATED :
     824             :         case SHORT : // no quarter data for this, defaults to ABBREVIATED
     825           0 :             count = fStandaloneShortQuartersCount;
     826           0 :             returnValue = fStandaloneShortQuarters;
     827           0 :             break;
     828             :         case NARROW :
     829           0 :             count = 0;
     830           0 :             returnValue = NULL;
     831           0 :             break;
     832             :         case DT_WIDTH_COUNT :
     833           0 :             break;
     834             :         }
     835           0 :         break;
     836             :     case DT_CONTEXT_COUNT :
     837           0 :         break;
     838             :     }
     839           0 :     return returnValue;
     840             : }
     841             : 
     842             : UnicodeString&
     843           0 : DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
     844             : {
     845             :     // fastCopyFrom() - see assignArray comments
     846           0 :     return result.fastCopyFrom(fTimeSeparator);
     847             : }
     848             : 
     849             : const UnicodeString*
     850           0 : DateFormatSymbols::getAmPmStrings(int32_t &count) const
     851             : {
     852           0 :     count = fAmPmsCount;
     853           0 :     return fAmPms;
     854             : }
     855             : 
     856             : const UnicodeString*
     857           0 : DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
     858             : {
     859           0 :     count = fLeapMonthPatternsCount;
     860           0 :     return fLeapMonthPatterns;
     861             : }
     862             : 
     863             : const UnicodeString*
     864           0 : DateFormatSymbols::getYearNames(int32_t& count,
     865             :                                 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
     866             : {
     867           0 :     count = fShortYearNamesCount;
     868           0 :     return fShortYearNames;
     869             : }
     870             : 
     871             : void
     872           0 : DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
     873             :                                 DtContextType context, DtWidthType width)
     874             : {
     875           0 :     if (context == FORMAT && width == ABBREVIATED) {
     876           0 :         if (fShortYearNames) {
     877           0 :             delete[] fShortYearNames;
     878             :         }
     879           0 :         fShortYearNames = newUnicodeStringArray(count);
     880           0 :         uprv_arrayCopy(yearNames, fShortYearNames, count);
     881           0 :         fShortYearNamesCount = count;
     882             :     }
     883           0 : }
     884             : 
     885             : const UnicodeString*
     886           0 : DateFormatSymbols::getZodiacNames(int32_t& count,
     887             :                                 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
     888             : {
     889           0 :     count = fShortZodiacNamesCount;
     890           0 :     return fShortZodiacNames;
     891             : }
     892             : 
     893             : void
     894           0 : DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
     895             :                                 DtContextType context, DtWidthType width)
     896             : {
     897           0 :     if (context == FORMAT && width == ABBREVIATED) {
     898           0 :         if (fShortZodiacNames) {
     899           0 :             delete[] fShortZodiacNames;
     900             :         }
     901           0 :         fShortZodiacNames = newUnicodeStringArray(count);
     902           0 :         uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
     903           0 :         fShortZodiacNamesCount = count;
     904             :     }
     905           0 : }
     906             : 
     907             : //------------------------------------------------------
     908             : 
     909             : void
     910           0 : DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
     911             : {
     912             :     // delete the old list if we own it
     913           0 :     if (fEras)
     914           0 :         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           0 :     fEras = newUnicodeStringArray(count);
     919           0 :     uprv_arrayCopy(erasArray,fEras,  count);
     920           0 :     fErasCount = count;
     921           0 : }
     922             : 
     923             : void
     924           0 : DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
     925             : {
     926             :     // delete the old list if we own it
     927           0 :     if (fEraNames)
     928           0 :         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           0 :     fEraNames = newUnicodeStringArray(count);
     933           0 :     uprv_arrayCopy(eraNamesArray,fEraNames,  count);
     934           0 :     fEraNamesCount = count;
     935           0 : }
     936             : 
     937             : void
     938           0 : DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
     939             : {
     940             :     // delete the old list if we own it
     941           0 :     if (fNarrowEras)
     942           0 :         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           0 :     fNarrowEras = newUnicodeStringArray(count);
     947           0 :     uprv_arrayCopy(narrowErasArray,fNarrowEras,  count);
     948           0 :     fNarrowErasCount = count;
     949           0 : }
     950             : 
     951             : void
     952           0 : DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
     953             : {
     954             :     // delete the old list if we own it
     955           0 :     if (fMonths)
     956           0 :         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           0 :     fMonths = newUnicodeStringArray(count);
     961           0 :     uprv_arrayCopy( monthsArray,fMonths,count);
     962           0 :     fMonthsCount = count;
     963           0 : }
     964             : 
     965             : void
     966           0 : DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
     967             : {
     968             :     // delete the old list if we own it
     969           0 :     if (fShortMonths)
     970           0 :         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           0 :     fShortMonths = newUnicodeStringArray(count);
     975           0 :     uprv_arrayCopy(shortMonthsArray,fShortMonths,  count);
     976           0 :     fShortMonthsCount = count;
     977           0 : }
     978             : 
     979             : void
     980           0 : 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           0 :     switch (context) {
     987             :     case FORMAT :
     988           0 :         switch (width) {
     989             :         case WIDE :
     990           0 :             if (fMonths)
     991           0 :                 delete[] fMonths;
     992           0 :             fMonths = newUnicodeStringArray(count);
     993           0 :             uprv_arrayCopy( monthsArray,fMonths,count);
     994           0 :             fMonthsCount = count;
     995           0 :             break;
     996             :         case ABBREVIATED :
     997           0 :             if (fShortMonths)
     998           0 :                 delete[] fShortMonths;
     999           0 :             fShortMonths = newUnicodeStringArray(count);
    1000           0 :             uprv_arrayCopy( monthsArray,fShortMonths,count);
    1001           0 :             fShortMonthsCount = count;
    1002           0 :             break;
    1003             :         case NARROW :
    1004           0 :             if (fNarrowMonths)
    1005           0 :                 delete[] fNarrowMonths;
    1006           0 :             fNarrowMonths = newUnicodeStringArray(count);
    1007           0 :             uprv_arrayCopy( monthsArray,fNarrowMonths,count);
    1008           0 :             fNarrowMonthsCount = count;
    1009           0 :             break;
    1010             :         default :
    1011           0 :             break;
    1012             :         }
    1013           0 :         break;
    1014             :     case STANDALONE :
    1015           0 :         switch (width) {
    1016             :         case WIDE :
    1017           0 :             if (fStandaloneMonths)
    1018           0 :                 delete[] fStandaloneMonths;
    1019           0 :             fStandaloneMonths = newUnicodeStringArray(count);
    1020           0 :             uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
    1021           0 :             fStandaloneMonthsCount = count;
    1022           0 :             break;
    1023             :         case ABBREVIATED :
    1024           0 :             if (fStandaloneShortMonths)
    1025           0 :                 delete[] fStandaloneShortMonths;
    1026           0 :             fStandaloneShortMonths = newUnicodeStringArray(count);
    1027           0 :             uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
    1028           0 :             fStandaloneShortMonthsCount = count;
    1029           0 :             break;
    1030             :         case NARROW :
    1031           0 :            if (fStandaloneNarrowMonths)
    1032           0 :                 delete[] fStandaloneNarrowMonths;
    1033           0 :             fStandaloneNarrowMonths = newUnicodeStringArray(count);
    1034           0 :             uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
    1035           0 :             fStandaloneNarrowMonthsCount = count;
    1036           0 :             break;
    1037             :         default :
    1038           0 :             break;
    1039             :         }
    1040           0 :         break;
    1041             :     case DT_CONTEXT_COUNT :
    1042           0 :         break;
    1043             :     }
    1044           0 : }
    1045             : 
    1046           0 : void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
    1047             : {
    1048             :     // delete the old list if we own it
    1049           0 :     if (fWeekdays)
    1050           0 :         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           0 :     fWeekdays = newUnicodeStringArray(count);
    1055           0 :     uprv_arrayCopy(weekdaysArray,fWeekdays,count);
    1056           0 :     fWeekdaysCount = count;
    1057           0 : }
    1058             : 
    1059             : void
    1060           0 : DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
    1061             : {
    1062             :     // delete the old list if we own it
    1063           0 :     if (fShortWeekdays)
    1064           0 :         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           0 :     fShortWeekdays = newUnicodeStringArray(count);
    1069           0 :     uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
    1070           0 :     fShortWeekdaysCount = count;
    1071           0 : }
    1072             : 
    1073             : void
    1074           0 : 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           0 :     switch (context) {
    1081             :     case FORMAT :
    1082           0 :         switch (width) {
    1083             :         case WIDE :
    1084           0 :             if (fWeekdays)
    1085           0 :                 delete[] fWeekdays;
    1086           0 :             fWeekdays = newUnicodeStringArray(count);
    1087           0 :             uprv_arrayCopy(weekdaysArray, fWeekdays, count);
    1088           0 :             fWeekdaysCount = count;
    1089           0 :             break;
    1090             :         case ABBREVIATED :
    1091           0 :             if (fShortWeekdays)
    1092           0 :                 delete[] fShortWeekdays;
    1093           0 :             fShortWeekdays = newUnicodeStringArray(count);
    1094           0 :             uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
    1095           0 :             fShortWeekdaysCount = count;
    1096           0 :             break;
    1097             :         case SHORT :
    1098           0 :             if (fShorterWeekdays)
    1099           0 :                 delete[] fShorterWeekdays;
    1100           0 :             fShorterWeekdays = newUnicodeStringArray(count);
    1101           0 :             uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
    1102           0 :             fShorterWeekdaysCount = count;
    1103           0 :             break;
    1104             :         case NARROW :
    1105           0 :             if (fNarrowWeekdays)
    1106           0 :                 delete[] fNarrowWeekdays;
    1107           0 :             fNarrowWeekdays = newUnicodeStringArray(count);
    1108           0 :             uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
    1109           0 :             fNarrowWeekdaysCount = count;
    1110           0 :             break;
    1111             :         case DT_WIDTH_COUNT :
    1112           0 :             break;
    1113             :         }
    1114           0 :         break;
    1115             :     case STANDALONE :
    1116           0 :         switch (width) {
    1117             :         case WIDE :
    1118           0 :             if (fStandaloneWeekdays)
    1119           0 :                 delete[] fStandaloneWeekdays;
    1120           0 :             fStandaloneWeekdays = newUnicodeStringArray(count);
    1121           0 :             uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
    1122           0 :             fStandaloneWeekdaysCount = count;
    1123           0 :             break;
    1124             :         case ABBREVIATED :
    1125           0 :             if (fStandaloneShortWeekdays)
    1126           0 :                 delete[] fStandaloneShortWeekdays;
    1127           0 :             fStandaloneShortWeekdays = newUnicodeStringArray(count);
    1128           0 :             uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
    1129           0 :             fStandaloneShortWeekdaysCount = count;
    1130           0 :             break;
    1131             :         case SHORT :
    1132           0 :             if (fStandaloneShorterWeekdays)
    1133           0 :                 delete[] fStandaloneShorterWeekdays;
    1134           0 :             fStandaloneShorterWeekdays = newUnicodeStringArray(count);
    1135           0 :             uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
    1136           0 :             fStandaloneShorterWeekdaysCount = count;
    1137           0 :             break;
    1138             :         case NARROW :
    1139           0 :             if (fStandaloneNarrowWeekdays)
    1140           0 :                 delete[] fStandaloneNarrowWeekdays;
    1141           0 :             fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
    1142           0 :             uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
    1143           0 :             fStandaloneNarrowWeekdaysCount = count;
    1144           0 :             break;
    1145             :         case DT_WIDTH_COUNT :
    1146           0 :             break;
    1147             :         }
    1148           0 :         break;
    1149             :     case DT_CONTEXT_COUNT :
    1150           0 :         break;
    1151             :     }
    1152           0 : }
    1153             : 
    1154             : void
    1155           0 : 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           0 :     switch (context) {
    1162             :     case FORMAT :
    1163           0 :         switch (width) {
    1164             :         case WIDE :
    1165           0 :             if (fQuarters)
    1166           0 :                 delete[] fQuarters;
    1167           0 :             fQuarters = newUnicodeStringArray(count);
    1168           0 :             uprv_arrayCopy( quartersArray,fQuarters,count);
    1169           0 :             fQuartersCount = count;
    1170           0 :             break;
    1171             :         case ABBREVIATED :
    1172           0 :             if (fShortQuarters)
    1173           0 :                 delete[] fShortQuarters;
    1174           0 :             fShortQuarters = newUnicodeStringArray(count);
    1175           0 :             uprv_arrayCopy( quartersArray,fShortQuarters,count);
    1176           0 :             fShortQuartersCount = count;
    1177           0 :             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           0 :             break;
    1187             :         default :
    1188           0 :             break;
    1189             :         }
    1190           0 :         break;
    1191             :     case STANDALONE :
    1192           0 :         switch (width) {
    1193             :         case WIDE :
    1194           0 :             if (fStandaloneQuarters)
    1195           0 :                 delete[] fStandaloneQuarters;
    1196           0 :             fStandaloneQuarters = newUnicodeStringArray(count);
    1197           0 :             uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
    1198           0 :             fStandaloneQuartersCount = count;
    1199           0 :             break;
    1200             :         case ABBREVIATED :
    1201           0 :             if (fStandaloneShortQuarters)
    1202           0 :                 delete[] fStandaloneShortQuarters;
    1203           0 :             fStandaloneShortQuarters = newUnicodeStringArray(count);
    1204           0 :             uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
    1205           0 :             fStandaloneShortQuartersCount = count;
    1206           0 :             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           0 :             break;
    1216             :         default :
    1217           0 :             break;
    1218             :         }
    1219           0 :         break;
    1220             :     case DT_CONTEXT_COUNT :
    1221           0 :         break;
    1222             :     }
    1223           0 : }
    1224             : 
    1225             : void
    1226           0 : DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
    1227             : {
    1228             :     // delete the old list if we own it
    1229           0 :     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           0 :     fAmPms = newUnicodeStringArray(count);
    1234           0 :     uprv_arrayCopy(amPmsArray,fAmPms,count);
    1235           0 :     fAmPmsCount = count;
    1236           0 : }
    1237             : 
    1238             : void
    1239           0 : DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
    1240             : {
    1241           0 :     fTimeSeparator = newTimeSeparator;
    1242           0 : }
    1243             : 
    1244             : const UnicodeString**
    1245           0 : DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
    1246             : {
    1247           0 :     const UnicodeString **result = NULL;
    1248             : 
    1249           0 :     umtx_lock(&LOCK);
    1250           0 :     if (fZoneStrings == NULL) {
    1251           0 :         if (fLocaleZoneStrings == NULL) {
    1252           0 :             ((DateFormatSymbols*)this)->initZoneStringsArray();
    1253             :         }
    1254           0 :         result = (const UnicodeString**)fLocaleZoneStrings;
    1255             :     } else {
    1256           0 :         result = (const UnicodeString**)fZoneStrings;
    1257             :     }
    1258           0 :     rowCount = fZoneStringsRowCount;
    1259           0 :     columnCount = fZoneStringsColCount;
    1260           0 :     umtx_unlock(&LOCK);
    1261             : 
    1262           0 :     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           0 : DateFormatSymbols::initZoneStringsArray(void) {
    1271           0 :     if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
    1272           0 :         return;
    1273             :     }
    1274             : 
    1275           0 :     UErrorCode status = U_ZERO_ERROR;
    1276             : 
    1277           0 :     StringEnumeration *tzids = NULL;
    1278           0 :     UnicodeString ** zarray = NULL;
    1279           0 :     TimeZoneNames *tzNames = NULL;
    1280           0 :     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           0 :         tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
    1291           0 :         rows = tzids->count(status);
    1292           0 :         if (U_FAILURE(status)) {
    1293           0 :             break;
    1294             :         }
    1295             : 
    1296             :         // Allocate array
    1297           0 :         int32_t size = rows * sizeof(UnicodeString*);
    1298           0 :         zarray = (UnicodeString**)uprv_malloc(size);
    1299           0 :         if (zarray == NULL) {
    1300           0 :             status = U_MEMORY_ALLOCATION_ERROR;
    1301           0 :             break;
    1302             :         }
    1303           0 :         uprv_memset(zarray, 0, size);
    1304             : 
    1305           0 :         tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
    1306           0 :         tzNames->loadAllDisplayNames(status);
    1307           0 :         if (U_FAILURE(status)) { break; }
    1308             : 
    1309             :         const UnicodeString *tzid;
    1310           0 :         int32_t i = 0;
    1311           0 :         UDate now = Calendar::getNow();
    1312           0 :         UnicodeString tzDispName;
    1313             : 
    1314           0 :         while ((tzid = tzids->snext(status))) {
    1315           0 :             if (U_FAILURE(status)) {
    1316           0 :                 break;
    1317             :             }
    1318             : 
    1319           0 :             zarray[i] = new UnicodeString[5];
    1320           0 :             if (zarray[i] == NULL) {
    1321           0 :                 status = U_MEMORY_ALLOCATION_ERROR;
    1322           0 :                 break;
    1323             :             }
    1324             : 
    1325           0 :             zarray[i][0].setTo(*tzid);
    1326           0 :             tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
    1327           0 :             i++;
    1328             :         }
    1329             : 
    1330             :     } while (FALSE);
    1331             : 
    1332           0 :     if (U_FAILURE(status)) {
    1333           0 :         if (zarray) {
    1334           0 :             for (int32_t i = 0; i < rows; i++) {
    1335           0 :                 if (zarray[i]) {
    1336           0 :                     delete[] zarray[i];
    1337             :                 }
    1338             :             }
    1339           0 :             uprv_free(zarray);
    1340           0 :             zarray = NULL;
    1341             :         }
    1342             :     }
    1343             : 
    1344           0 :     if (tzNames) {
    1345           0 :         delete tzNames;
    1346             :     }
    1347           0 :     if (tzids) {
    1348           0 :         delete tzids;
    1349             :     }
    1350             : 
    1351           0 :     fLocaleZoneStrings = zarray;
    1352           0 :     fZoneStringsRowCount = rows;
    1353           0 :     fZoneStringsColCount = 1 + NUM_TYPES;
    1354             : }
    1355             : 
    1356             : void
    1357           0 : 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           0 :     disposeZoneStrings();
    1362             :     // we always own the new list, which we create here (we duplicate rather
    1363             :     // than adopting the list passed in)
    1364           0 :     fZoneStringsRowCount = rowCount;
    1365           0 :     fZoneStringsColCount = columnCount;
    1366           0 :     createZoneStrings((const UnicodeString**)strings);
    1367           0 : }
    1368             : 
    1369             : //------------------------------------------------------
    1370             : 
    1371             : const char16_t * U_EXPORT2
    1372           0 : DateFormatSymbols::getPatternUChars(void)
    1373             : {
    1374           0 :     return gPatternChars;
    1375             : }
    1376             : 
    1377             : UDateFormatField U_EXPORT2
    1378           0 : DateFormatSymbols::getPatternCharIndex(UChar c) {
    1379           0 :     const UChar *p = u_strchr(gPatternChars, c);
    1380           0 :     if (p == NULL) {
    1381           0 :         return UDAT_FIELD_COUNT;
    1382             :     } else {
    1383           0 :         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           0 : DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
    1417           0 :     if (f == UDAT_FIELD_COUNT) {
    1418           0 :         return FALSE;
    1419             :     }
    1420           0 :     uint64_t flag = ((uint64_t)1 << f);
    1421           0 :     return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
    1422             : }
    1423             : 
    1424             : UBool U_EXPORT2
    1425           0 : DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
    1426           0 :     return isNumericField(getPatternCharIndex(c), count);
    1427             : }
    1428             : 
    1429             : //------------------------------------------------------
    1430             : 
    1431             : UnicodeString&
    1432           0 : DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
    1433             : {
    1434             :     // fastCopyFrom() - see assignArray comments
    1435           0 :     return result.fastCopyFrom(fLocalPatternChars);
    1436             : }
    1437             : 
    1438             : //------------------------------------------------------
    1439             : 
    1440             : void
    1441           0 : DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
    1442             : {
    1443           0 :     fLocalPatternChars = newLocalPatternChars;
    1444           0 : }
    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           0 :     CalendarDataSink(UErrorCode& status)
    1520           0 :     :   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           0 :         resourcesToVisit(NULL), aliasRelativePath() {
    1525           0 :         if (U_FAILURE(status)) { return; }
    1526             :     }
    1527             :     virtual ~CalendarDataSink();
    1528             : 
    1529             :     // Configure the CalendarSink to visit all the resources
    1530           0 :     void visitAllResources() {
    1531           0 :         resourcesToVisit.adoptInstead(NULL);
    1532           0 :     }
    1533             : 
    1534             :     // Actions to be done before enumerating
    1535           0 :     void preEnumerate(const UnicodeString &calendarType) {
    1536           0 :         currentCalendarType = calendarType;
    1537           0 :         nextCalendarType.setToBogus();
    1538           0 :         aliasPathPairs.removeAllElements();
    1539           0 :     }
    1540             : 
    1541           0 :     virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
    1542           0 :         if (U_FAILURE(errorCode)) { return; }
    1543           0 :         U_ASSERT(!currentCalendarType.isEmpty());
    1544             : 
    1545             :         // Stores the resources to visit on the next calendar.
    1546           0 :         LocalPointer<UVector> resourcesToVisitNext(NULL);
    1547           0 :         ResourceTable calendarData = value.getTable(errorCode);
    1548           0 :         if (U_FAILURE(errorCode)) { return; }
    1549             : 
    1550             :         // Enumerate all resources for this calendar
    1551           0 :         for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
    1552           0 :             UnicodeString keyUString(key, -1, US_INV);
    1553             : 
    1554             :             // == Handle aliases ==
    1555           0 :             AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
    1556           0 :             if (U_FAILURE(errorCode)) { return; }
    1557           0 :             if (aliasType == GREGORIAN) {
    1558             :                 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
    1559           0 :                 continue;
    1560             : 
    1561           0 :             } 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           0 :                 if (resourcesToVisitNext.isNull()) {
    1565             :                     resourcesToVisitNext
    1566           0 :                         .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, errorCode),
    1567           0 :                                                        errorCode);
    1568           0 :                     if (U_FAILURE(errorCode)) { return; }
    1569             :                 }
    1570           0 :                 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
    1571           0 :                 resourcesToVisitNext->addElement(aliasRelativePathCopy.getAlias(), errorCode);
    1572           0 :                 if (U_FAILURE(errorCode)) { return; }
    1573             :                 // Only release ownership after resourcesToVisitNext takes it (no error happened):
    1574           0 :                 aliasRelativePathCopy.orphan();
    1575           0 :                 continue;
    1576             : 
    1577           0 :             } else if (aliasType == SAME_CALENDAR) {
    1578             :                 // Register same-calendar alias
    1579           0 :                 if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) {
    1580           0 :                     LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
    1581           0 :                     aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
    1582           0 :                     if (U_FAILURE(errorCode)) { return; }
    1583             :                     // Only release ownership after aliasPathPairs takes it (no error happened):
    1584           0 :                     aliasRelativePathCopy.orphan();
    1585           0 :                     LocalPointer<UnicodeString> keyUStringCopy(new UnicodeString(keyUString), errorCode);
    1586           0 :                     aliasPathPairs.addElement(keyUStringCopy.getAlias(), errorCode);
    1587           0 :                     if (U_FAILURE(errorCode)) { return; }
    1588             :                     // Only release ownership after aliasPathPairs takes it (no error happened):
    1589           0 :                     keyUStringCopy.orphan();
    1590             :                 }
    1591           0 :                 continue;
    1592             :             }
    1593             : 
    1594             :             // Only visit the resources that were referenced by an alias on the previous calendar
    1595             :             // (AmPmMarkersAbbr is an exception).
    1596           0 :             if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
    1597           0 :                 && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
    1598             : 
    1599             :             // == Handle data ==
    1600           0 :             if (uprv_strcmp(key, gAmPmMarkersTag) == 0
    1601           0 :                 || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
    1602           0 :                 || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
    1603           0 :                 if (arrays.get(keyUString) == NULL) {
    1604           0 :                     ResourceArray resourceArray = value.getArray(errorCode);
    1605           0 :                     int32_t arraySize = resourceArray.getSize();
    1606           0 :                     LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
    1607           0 :                     value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
    1608           0 :                     arrays.put(keyUString, stringArray.orphan(), errorCode);
    1609           0 :                     arraySizes.puti(keyUString, arraySize, errorCode);
    1610           0 :                     if (U_FAILURE(errorCode)) { return; }
    1611           0 :                 }
    1612           0 :             } else if (uprv_strcmp(key, gErasTag) == 0
    1613           0 :                        || uprv_strcmp(key, gDayNamesTag) == 0
    1614           0 :                        || uprv_strcmp(key, gMonthNamesTag) == 0
    1615           0 :                        || uprv_strcmp(key, gQuartersTag) == 0
    1616           0 :                        || uprv_strcmp(key, gDayPeriodTag) == 0
    1617           0 :                        || uprv_strcmp(key, gMonthPatternsTag) == 0
    1618           0 :                        || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
    1619           0 :                 processResource(keyUString, key, value, errorCode);
    1620             :             }
    1621             :         }
    1622             : 
    1623             :         // Apply same-calendar aliases
    1624             :         UBool modified;
    1625           0 :         do {
    1626           0 :             modified = false;
    1627           0 :             for (int32_t i = 0; i < aliasPathPairs.size();) {
    1628           0 :                 UBool mod = false;
    1629           0 :                 UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
    1630             :                 UnicodeString *aliasArray;
    1631             :                 Hashtable *aliasMap;
    1632           0 :                 if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != NULL) {
    1633             :                     // Clone the array
    1634           0 :                     int32_t aliasArraySize = arraySizes.geti(*alias);
    1635           0 :                     LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
    1636           0 :                     if (U_FAILURE(errorCode)) { return; }
    1637           0 :                     uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
    1638             :                     // Put the array on the 'arrays' map
    1639           0 :                     UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
    1640           0 :                     arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
    1641           0 :                     arraySizes.puti(*path, aliasArraySize, errorCode);
    1642           0 :                     if (U_FAILURE(errorCode)) { return; }
    1643           0 :                     mod = true;
    1644           0 :                 } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != NULL) {
    1645           0 :                     UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
    1646           0 :                     maps.put(*path, aliasMap, errorCode);
    1647           0 :                     if (U_FAILURE(errorCode)) { return; }
    1648           0 :                     mod = true;
    1649             :                 }
    1650           0 :                 if (mod) {
    1651           0 :                     aliasPathPairs.removeElementAt(i + 1);
    1652           0 :                     aliasPathPairs.removeElementAt(i);
    1653           0 :                     modified = true;
    1654             :                 } else {
    1655           0 :                     i += 2;
    1656             :                 }
    1657             :             }
    1658           0 :         } while (modified && !aliasPathPairs.isEmpty());
    1659             : 
    1660             :         // Set the resources to visit on the next calendar
    1661           0 :         if (!resourcesToVisitNext.isNull()) {
    1662           0 :             resourcesToVisit.moveFrom(resourcesToVisitNext);
    1663             :         }
    1664             :     }
    1665             : 
    1666             :     // Process the nested resource bundle tables
    1667           0 :     void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
    1668           0 :         if (U_FAILURE(errorCode)) return;
    1669             : 
    1670           0 :         ResourceTable table = value.getTable(errorCode);
    1671           0 :         if (U_FAILURE(errorCode)) return;
    1672           0 :         Hashtable* stringMap = NULL;
    1673             : 
    1674             :         // Iterate over all the elements of the table and add them to the map
    1675           0 :         for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
    1676           0 :             UnicodeString keyUString(key, -1, US_INV);
    1677             : 
    1678             :             // Ignore '%variant' keys
    1679           0 :             if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
    1680           0 :                 continue;
    1681             :             }
    1682             : 
    1683             :             // == Handle String elements ==
    1684           0 :             if (value.getType() == URES_STRING) {
    1685             :                 // We are on a leaf, store the map elements into the stringMap
    1686           0 :                 if (i == 0) {
    1687           0 :                     LocalPointer<Hashtable> stringMapPtr(new Hashtable(FALSE, errorCode), errorCode);
    1688           0 :                     stringMap = stringMapPtr.getAlias();
    1689           0 :                     maps.put(path, stringMap, errorCode);
    1690             :                     // mapRefs will take ownership of 'stringMap':
    1691           0 :                     mapRefs.addElement(stringMap, errorCode);
    1692           0 :                     if (U_FAILURE(errorCode)) { return; }
    1693             :                     // Only release ownership after mapRefs takes it (no error happened):
    1694           0 :                     stringMapPtr.orphan();
    1695           0 :                     stringMap->setValueDeleter(uprv_deleteUObject);
    1696             :                 }
    1697           0 :                 U_ASSERT(stringMap != NULL);
    1698             :                 int32_t valueStringSize;
    1699           0 :                 const UChar *valueString = value.getString(valueStringSize, errorCode);
    1700           0 :                 if (U_FAILURE(errorCode)) { return; }
    1701           0 :                 LocalPointer<UnicodeString> valueUString(new UnicodeString(TRUE, valueString, valueStringSize), errorCode);
    1702           0 :                 stringMap->put(keyUString, valueUString.orphan(), errorCode);
    1703           0 :                 if (U_FAILURE(errorCode)) { return; }
    1704           0 :                 continue;
    1705             :             }
    1706           0 :             U_ASSERT(stringMap == NULL);
    1707             : 
    1708             :             // Store the current path's length and append the current key to the path.
    1709           0 :             int32_t pathLength = path.length();
    1710           0 :             path.append(SOLIDUS).append(keyUString);
    1711             : 
    1712             :             // In cyclicNameSets ignore everything but years/format/abbreviated
    1713             :             // and zodiacs/format/abbreviated
    1714           0 :             if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
    1715           0 :                 UBool skip = TRUE;
    1716           0 :                 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
    1717           0 :                 int32_t length = 0;
    1718           0 :                 if (startIndex == path.length()
    1719           0 :                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
    1720           0 :                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
    1721           0 :                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
    1722           0 :                     startIndex += length;
    1723           0 :                     length = 0;
    1724           0 :                     if (startIndex == path.length()
    1725           0 :                         || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
    1726           0 :                         startIndex += length;
    1727           0 :                         length = 0;
    1728           0 :                         if (startIndex == path.length()
    1729           0 :                             || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
    1730           0 :                             skip = FALSE;
    1731             :                         }
    1732             :                     }
    1733             :                 }
    1734           0 :                 if (skip) {
    1735             :                     // Drop the latest key on the path and continue
    1736           0 :                     path.retainBetween(0, pathLength);
    1737           0 :                     continue;
    1738             :                 }
    1739             :             }
    1740             : 
    1741             :             // == Handle aliases ==
    1742           0 :             if (arrays.get(path) != NULL || maps.get(path) != NULL) {
    1743             :                 // Drop the latest key on the path and continue
    1744           0 :                 path.retainBetween(0, pathLength);
    1745           0 :                 continue;
    1746             :             }
    1747             : 
    1748           0 :             AliasType aliasType = processAliasFromValue(path, value, errorCode);
    1749           0 :             if (U_FAILURE(errorCode)) { return; }
    1750           0 :             if (aliasType == SAME_CALENDAR) {
    1751             :                 // Store the alias path and the current path on aliasPathPairs
    1752           0 :                 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
    1753           0 :                 aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
    1754           0 :                 if (U_FAILURE(errorCode)) { return; }
    1755             :                 // Only release ownership after aliasPathPairs takes it (no error happened):
    1756           0 :                 aliasRelativePathCopy.orphan();
    1757           0 :                 LocalPointer<UnicodeString> pathCopy(new UnicodeString(path), errorCode);
    1758           0 :                 aliasPathPairs.addElement(pathCopy.getAlias(), errorCode);
    1759           0 :                 if (U_FAILURE(errorCode)) { return; }
    1760             :                 // Only release ownership after aliasPathPairs takes it (no error happened):
    1761           0 :                 pathCopy.orphan();
    1762             : 
    1763             :                 // Drop the latest key on the path and continue
    1764           0 :                 path.retainBetween(0, pathLength);
    1765           0 :                 continue;
    1766             :             }
    1767           0 :             U_ASSERT(aliasType == NONE);
    1768             : 
    1769             :             // == Handle data ==
    1770           0 :             if (value.getType() == URES_ARRAY) {
    1771             :                 // We are on a leaf, store the array
    1772           0 :                 ResourceArray rDataArray = value.getArray(errorCode);
    1773           0 :                 int32_t dataArraySize = rDataArray.getSize();
    1774           0 :                 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
    1775           0 :                 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
    1776           0 :                 arrays.put(path, dataArray.orphan(), errorCode);
    1777           0 :                 arraySizes.puti(path, dataArraySize, errorCode);
    1778           0 :                 if (U_FAILURE(errorCode)) { return; }
    1779           0 :             } else if (value.getType() == URES_TABLE) {
    1780             :                 // We are not on a leaf, recursively process the subtable.
    1781           0 :                 processResource(path, key, value, errorCode);
    1782           0 :                 if (U_FAILURE(errorCode)) { return; }
    1783             :             }
    1784             : 
    1785             :             // Drop the latest key on the path
    1786           0 :             path.retainBetween(0, pathLength);
    1787             :         }
    1788             :     }
    1789             : 
    1790             :     // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
    1791           0 :     AliasType processAliasFromValue(UnicodeString &currentRelativePath, ResourceValue &value,
    1792             :                                     UErrorCode &errorCode) {
    1793           0 :         if (U_FAILURE(errorCode)) { return NONE; }
    1794             : 
    1795           0 :         if (value.getType() == URES_ALIAS) {
    1796             :             int32_t aliasPathSize;
    1797           0 :             const UChar* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
    1798           0 :             if (U_FAILURE(errorCode)) { return NONE; }
    1799           0 :             UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
    1800           0 :             const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
    1801           0 :             if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
    1802           0 :                 && aliasPath.length() > aliasPrefixLength) {
    1803           0 :                 int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
    1804           0 :                 if (typeLimit > aliasPrefixLength) {
    1805             :                     const UnicodeString aliasCalendarType =
    1806           0 :                         aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
    1807           0 :                     aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
    1808             : 
    1809           0 :                     if (currentCalendarType == aliasCalendarType
    1810           0 :                         && currentRelativePath != aliasRelativePath) {
    1811             :                         // If we have an alias to the same calendar, the path to the resource must be different
    1812           0 :                         return SAME_CALENDAR;
    1813             : 
    1814           0 :                     } else if (currentCalendarType != aliasCalendarType
    1815           0 :                                && currentRelativePath == aliasRelativePath) {
    1816             :                         // If we have an alias to a different calendar, the path to the resource must be the same
    1817           0 :                         if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
    1818           0 :                             return GREGORIAN;
    1819           0 :                         } else if (nextCalendarType.isBogus()) {
    1820           0 :                             nextCalendarType = aliasCalendarType;
    1821           0 :                             return DIFFERENT_CALENDAR;
    1822           0 :                         } else if (nextCalendarType == aliasCalendarType) {
    1823           0 :                             return DIFFERENT_CALENDAR;
    1824             :                         }
    1825             :                     }
    1826             :                 }
    1827             :             }
    1828           0 :             errorCode = U_INTERNAL_PROGRAM_ERROR;
    1829           0 :             return NONE;
    1830             :         }
    1831           0 :         return NONE;
    1832             :     }
    1833             : 
    1834             :     // Deleter function to be used by 'arrays'
    1835           0 :     static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
    1836           0 :         delete[] static_cast<UnicodeString *>(uArray);
    1837           0 :     }
    1838             : 
    1839             :     // Deleter function to be used by 'maps'
    1840           0 :     static void U_CALLCONV deleteHashtable(void *table) {
    1841           0 :         delete static_cast<Hashtable *>(table);
    1842           0 :     }
    1843             : };
    1844             : // Virtual destructors have to be defined out of line
    1845           0 : CalendarDataSink::~CalendarDataSink() {
    1846           0 :     arrays.setValueDeleter(deleteUnicodeStringArray);
    1847           0 : }
    1848             : }
    1849             : 
    1850             : //------------------------------------------------------
    1851             : 
    1852             : static void
    1853           0 : initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
    1854           0 :     if (U_SUCCESS(status)) {
    1855           0 :         length = numStr;
    1856           0 :         *field = newUnicodeStringArray((size_t)numStr);
    1857           0 :         if (*field) {
    1858           0 :             for(int32_t i = 0; i<length; i++) {
    1859             :                 // readonly aliases - all "data" strings are constant
    1860             :                 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
    1861           0 :                 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
    1862             :             }
    1863             :         }
    1864             :         else {
    1865           0 :             length = 0;
    1866           0 :             status = U_MEMORY_ALLOCATION_ERROR;
    1867             :         }
    1868             :     }
    1869           0 : }
    1870             : 
    1871             : static void
    1872           0 : initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
    1873           0 :     if (U_SUCCESS(status)) {
    1874           0 :         UnicodeString keyUString(key.data(), -1, US_INV);
    1875           0 :         UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
    1876             : 
    1877           0 :         if (array != NULL) {
    1878           0 :             length = sink.arraySizes.geti(keyUString);
    1879           0 :             *field = array;
    1880             :             // DateFormatSymbols takes ownership of the array:
    1881           0 :             sink.arrays.remove(keyUString);
    1882             :         } else {
    1883           0 :             length = 0;
    1884           0 :             status = U_MISSING_RESOURCE_ERROR;
    1885             :         }
    1886             :     }
    1887           0 : }
    1888             : 
    1889             : static void
    1890           0 : initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
    1891           0 :     if (U_SUCCESS(status)) {
    1892           0 :         UnicodeString keyUString(key.data(), -1, US_INV);
    1893           0 :         UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
    1894             : 
    1895           0 :         if (array != NULL) {
    1896           0 :             int32_t arrayLength = sink.arraySizes.geti(keyUString);
    1897           0 :             length = arrayLength + arrayOffset;
    1898           0 :             *field = new UnicodeString[length];
    1899           0 :             if (*field == NULL) {
    1900           0 :                 status = U_MEMORY_ALLOCATION_ERROR;
    1901           0 :                 return;
    1902             :             }
    1903           0 :             uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
    1904             :         } else {
    1905           0 :             length = 0;
    1906           0 :             status = U_MISSING_RESOURCE_ERROR;
    1907             :         }
    1908             :     }
    1909             : }
    1910             : 
    1911             : static void
    1912           0 : initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
    1913           0 :     field[index].remove();
    1914           0 :     if (U_SUCCESS(status)) {
    1915           0 :         UnicodeString pathUString(path.data(), -1, US_INV);
    1916           0 :         Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
    1917           0 :         if (leapMonthTable != NULL) {
    1918           0 :             UnicodeString leapLabel(FALSE, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
    1919           0 :             UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
    1920           0 :             if (leapMonthPattern != NULL) {
    1921           0 :                 field[index].fastCopyFrom(*leapMonthPattern);
    1922             :             } else {
    1923           0 :                 field[index].setToBogus();
    1924             :             }
    1925           0 :             return;
    1926             :         }
    1927           0 :         status = U_MISSING_RESOURCE_ERROR;
    1928             :     }
    1929             : }
    1930             : 
    1931             : static CharString
    1932           0 : &buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
    1933           0 :     return path.clear().append(segment1, -1, errorCode);
    1934             : }
    1935             : 
    1936             : static CharString
    1937           0 : &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
    1938             :                    UErrorCode &errorCode) {
    1939           0 :     return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
    1940           0 :                                                        .append(segment2, -1, errorCode);
    1941             : }
    1942             : 
    1943             : static CharString
    1944           0 : &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
    1945             :                    const char* segment3, UErrorCode &errorCode) {
    1946           0 :     return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
    1947           0 :                                                                  .append(segment3, -1, errorCode);
    1948             : }
    1949             : 
    1950             : static CharString
    1951           0 : &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
    1952             :                    const char* segment3, const char* segment4, UErrorCode &errorCode) {
    1953           0 :     return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
    1954           0 :                                                                            .append(segment4, -1, errorCode);
    1955             : }
    1956             : 
    1957             : typedef struct {
    1958             :     const char * usageTypeName;
    1959             :     DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
    1960             : } ContextUsageTypeNameToEnumValue;
    1961             : 
    1962             : static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
    1963             :    // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
    1964             :     { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
    1965             :     { "day-narrow",     DateFormatSymbols::kCapContextUsageDayNarrow },
    1966             :     { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
    1967             :     { "era-abbr",       DateFormatSymbols::kCapContextUsageEraAbbrev },
    1968             :     { "era-name",       DateFormatSymbols::kCapContextUsageEraWide },
    1969             :     { "era-narrow",     DateFormatSymbols::kCapContextUsageEraNarrow },
    1970             :     { "metazone-long",  DateFormatSymbols::kCapContextUsageMetazoneLong },
    1971             :     { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
    1972             :     { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
    1973             :     { "month-narrow",   DateFormatSymbols::kCapContextUsageMonthNarrow },
    1974             :     { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
    1975             :     { "zone-long",      DateFormatSymbols::kCapContextUsageZoneLong },
    1976             :     { "zone-short",     DateFormatSymbols::kCapContextUsageZoneShort },
    1977             :     { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
    1978             : };
    1979             : 
    1980             : // Resource keys to look up localized strings for day periods.
    1981             : // The first one must be midnight and the second must be noon, so that their indices coincide
    1982             : // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
    1983             : static const char *dayPeriodKeys[] = {"midnight", "noon",
    1984             :                          "morning1", "afternoon1", "evening1", "night1",
    1985             :                          "morning2", "afternoon2", "evening2", "night2"};
    1986             : 
    1987           0 : UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
    1988             :                                     int32_t &stringCount,  UErrorCode &status) {
    1989           0 :     if (U_FAILURE(status)) { return NULL; }
    1990             : 
    1991           0 :     UnicodeString pathUString(path.data(), -1, US_INV);
    1992           0 :     Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
    1993             : 
    1994           0 :     stringCount = UPRV_LENGTHOF(dayPeriodKeys);
    1995           0 :     UnicodeString *strings = new UnicodeString[stringCount];
    1996           0 :     if (strings == NULL) {
    1997           0 :         status = U_MEMORY_ALLOCATION_ERROR;
    1998           0 :         return NULL;
    1999             :     }
    2000             : 
    2001           0 :     if (map != NULL) {
    2002           0 :         for (int32_t i = 0; i < stringCount; ++i) {
    2003           0 :             UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
    2004           0 :             UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
    2005           0 :             if (dayPeriod != NULL) {
    2006           0 :                 strings[i].fastCopyFrom(*dayPeriod);
    2007             :             } else {
    2008           0 :                 strings[i].setToBogus();
    2009             :             }
    2010             :         }
    2011             :     } else {
    2012           0 :         for (int32_t i = 0; i < stringCount; i++) {
    2013           0 :             strings[i].setToBogus();
    2014             :         }
    2015             :     }
    2016           0 :     return strings;
    2017             : }
    2018             : 
    2019             : 
    2020             : void
    2021           0 : DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
    2022             : {
    2023           0 :     int32_t len = 0;
    2024             :     /* In case something goes wrong, initialize all of the data to NULL. */
    2025           0 :     fEras = NULL;
    2026           0 :     fErasCount = 0;
    2027           0 :     fEraNames = NULL;
    2028           0 :     fEraNamesCount = 0;
    2029           0 :     fNarrowEras = NULL;
    2030           0 :     fNarrowErasCount = 0;
    2031           0 :     fMonths = NULL;
    2032           0 :     fMonthsCount=0;
    2033           0 :     fShortMonths = NULL;
    2034           0 :     fShortMonthsCount=0;
    2035           0 :     fNarrowMonths = NULL;
    2036           0 :     fNarrowMonthsCount=0;
    2037           0 :     fStandaloneMonths = NULL;
    2038           0 :     fStandaloneMonthsCount=0;
    2039           0 :     fStandaloneShortMonths = NULL;
    2040           0 :     fStandaloneShortMonthsCount=0;
    2041           0 :     fStandaloneNarrowMonths = NULL;
    2042           0 :     fStandaloneNarrowMonthsCount=0;
    2043           0 :     fWeekdays = NULL;
    2044           0 :     fWeekdaysCount=0;
    2045           0 :     fShortWeekdays = NULL;
    2046           0 :     fShortWeekdaysCount=0;
    2047           0 :     fShorterWeekdays = NULL;
    2048           0 :     fShorterWeekdaysCount=0;
    2049           0 :     fNarrowWeekdays = NULL;
    2050           0 :     fNarrowWeekdaysCount=0;
    2051           0 :     fStandaloneWeekdays = NULL;
    2052           0 :     fStandaloneWeekdaysCount=0;
    2053           0 :     fStandaloneShortWeekdays = NULL;
    2054           0 :     fStandaloneShortWeekdaysCount=0;
    2055           0 :     fStandaloneShorterWeekdays = NULL;
    2056           0 :     fStandaloneShorterWeekdaysCount=0;
    2057           0 :     fStandaloneNarrowWeekdays = NULL;
    2058           0 :     fStandaloneNarrowWeekdaysCount=0;
    2059           0 :     fAmPms = NULL;
    2060           0 :     fAmPmsCount=0;
    2061           0 :     fNarrowAmPms = NULL;
    2062           0 :     fNarrowAmPmsCount=0;
    2063           0 :     fTimeSeparator.setToBogus();
    2064           0 :     fQuarters = NULL;
    2065           0 :     fQuartersCount = 0;
    2066           0 :     fShortQuarters = NULL;
    2067           0 :     fShortQuartersCount = 0;
    2068           0 :     fStandaloneQuarters = NULL;
    2069           0 :     fStandaloneQuartersCount = 0;
    2070           0 :     fStandaloneShortQuarters = NULL;
    2071           0 :     fStandaloneShortQuartersCount = 0;
    2072           0 :     fLeapMonthPatterns = NULL;
    2073           0 :     fLeapMonthPatternsCount = 0;
    2074           0 :     fShortYearNames = NULL;
    2075           0 :     fShortYearNamesCount = 0;
    2076           0 :     fShortZodiacNames = NULL;
    2077           0 :     fShortZodiacNamesCount = 0;
    2078           0 :     fZoneStringsRowCount = 0;
    2079           0 :     fZoneStringsColCount = 0;
    2080           0 :     fZoneStrings = NULL;
    2081           0 :     fLocaleZoneStrings = NULL;
    2082           0 :     fAbbreviatedDayPeriods = NULL;
    2083           0 :     fAbbreviatedDayPeriodsCount = 0;
    2084           0 :     fWideDayPeriods = NULL;
    2085           0 :     fWideDayPeriodsCount = 0;
    2086           0 :     fNarrowDayPeriods = NULL;
    2087           0 :     fNarrowDayPeriodsCount = 0;
    2088           0 :     fStandaloneAbbreviatedDayPeriods = NULL;
    2089           0 :     fStandaloneAbbreviatedDayPeriodsCount = 0;
    2090           0 :     fStandaloneWideDayPeriods = NULL;
    2091           0 :     fStandaloneWideDayPeriodsCount = 0;
    2092           0 :     fStandaloneNarrowDayPeriods = NULL;
    2093           0 :     fStandaloneNarrowDayPeriodsCount = 0;
    2094           0 :     uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
    2095             : 
    2096             :     // We need to preserve the requested locale for
    2097             :     // lazy ZoneStringFormat instantiation.  ZoneStringFormat
    2098             :     // is region sensitive, thus, bundle locale bundle's locale
    2099             :     // is not sufficient.
    2100           0 :     fZSFLocale = locale;
    2101             : 
    2102           0 :     if (U_FAILURE(status)) return;
    2103             : 
    2104             :     // Create a CalendarDataSink to process this data and the resouce bundles
    2105           0 :     CalendarDataSink calendarSink(status);
    2106           0 :     UResourceBundle *rb = ures_open(NULL, locale.getBaseName(), &status);
    2107           0 :     UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, NULL, &status);
    2108             : 
    2109           0 :     if (U_FAILURE(status)) return;
    2110             : 
    2111             :     // Iterate over the resource bundle data following the fallbacks through different calendar types
    2112           0 :     UnicodeString calendarType((type != NULL && *type != '\0')? type : gGregorianTag, -1, US_INV);
    2113           0 :     while (!calendarType.isBogus()) {
    2114           0 :         CharString calendarTypeBuffer;
    2115           0 :         calendarTypeBuffer.appendInvariantChars(calendarType, status);
    2116           0 :         if (U_FAILURE(status)) { return; }
    2117           0 :         const char *calendarTypeCArray = calendarTypeBuffer.data();
    2118             : 
    2119             :         // Enumerate this calendar type. If the calendar is not found fallback to gregorian
    2120           0 :         UErrorCode oldStatus = status;
    2121           0 :         UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, NULL, &status);
    2122           0 :         if (status == U_MISSING_RESOURCE_ERROR) {
    2123           0 :             ures_close(ctb);
    2124           0 :             if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
    2125           0 :                 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
    2126           0 :                 calendarSink.visitAllResources();
    2127           0 :                 status = oldStatus;
    2128           0 :                 continue;
    2129             :             }
    2130           0 :             return;
    2131             :         }
    2132             : 
    2133           0 :         calendarSink.preEnumerate(calendarType);
    2134           0 :         ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
    2135           0 :         ures_close(ctb);
    2136           0 :         if (U_FAILURE(status)) break;
    2137             : 
    2138             :         // Stop loading when gregorian was loaded
    2139           0 :         if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
    2140           0 :             break;
    2141             :         }
    2142             : 
    2143             :         // Get the next calendar type to process from the sink
    2144           0 :         calendarType = calendarSink.nextCalendarType;
    2145             : 
    2146             :         // Gregorian is always the last fallback
    2147           0 :         if (calendarType.isBogus()) {
    2148           0 :             calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
    2149           0 :             calendarSink.visitAllResources();
    2150             :         }
    2151             :     }
    2152             : 
    2153             :     // CharString object to build paths
    2154           0 :     CharString path;
    2155             : 
    2156             :     // Load Leap Month Patterns
    2157           0 :     UErrorCode tempStatus = status;
    2158           0 :     fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
    2159           0 :     if (fLeapMonthPatterns) {
    2160           0 :         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
    2161           0 :                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
    2162           0 :         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
    2163           0 :                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
    2164           0 :         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
    2165           0 :                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
    2166           0 :         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
    2167           0 :                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
    2168           0 :         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
    2169           0 :                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
    2170           0 :         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
    2171           0 :                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
    2172           0 :         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
    2173           0 :                              buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
    2174           0 :         if (U_SUCCESS(tempStatus)) {
    2175             :             // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
    2176             :             // The ordering of the following statements is important.
    2177           0 :             if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
    2178           0 :                 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
    2179             :             };
    2180           0 :             if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
    2181           0 :                 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
    2182             :             };
    2183           0 :             if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
    2184           0 :                 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
    2185             :             };
    2186           0 :             if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
    2187           0 :                 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
    2188             :             };
    2189             :             // end of hack
    2190           0 :             fLeapMonthPatternsCount = kMonthPatternsCount;
    2191             :         } else {
    2192           0 :             delete[] fLeapMonthPatterns;
    2193           0 :             fLeapMonthPatterns = NULL;
    2194             :         }
    2195             :     }
    2196             : 
    2197             :     // Load cyclic names sets
    2198           0 :     tempStatus = status;
    2199           0 :     initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
    2200           0 :               buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
    2201           0 :     initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
    2202           0 :               buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
    2203             : 
    2204             :     // Load context transforms and capitalization
    2205           0 :     tempStatus = U_ZERO_ERROR;
    2206           0 :     UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
    2207           0 :     if (U_SUCCESS(tempStatus)) {
    2208           0 :         UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
    2209           0 :         if (U_SUCCESS(tempStatus)) {
    2210             :             UResourceBundle *contextTransformUsage;
    2211           0 :             while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
    2212           0 :                 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
    2213           0 :                 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
    2214           0 :                     const char* usageType = ures_getKey(contextTransformUsage);
    2215           0 :                     if (usageType != NULL) {
    2216           0 :                         const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
    2217           0 :                         int32_t compResult = 0;
    2218             :                         // linear search; list is short and we cannot be sure that bsearch is available
    2219           0 :                         while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
    2220           0 :                             ++typeMapPtr;
    2221             :                         }
    2222           0 :                         if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
    2223           0 :                             fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0];
    2224           0 :                             fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1];
    2225             :                         }
    2226             :                     }
    2227             :                 }
    2228           0 :                 tempStatus = U_ZERO_ERROR;
    2229           0 :                 ures_close(contextTransformUsage);
    2230             :             }
    2231           0 :             ures_close(contextTransforms);
    2232             :         }
    2233             : 
    2234           0 :         tempStatus = U_ZERO_ERROR;
    2235             :         const LocalPointer<NumberingSystem> numberingSystem(
    2236           0 :                 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
    2237           0 :         if (U_SUCCESS(tempStatus)) {
    2238             :             // These functions all fail gracefully if passed NULL pointers and
    2239             :             // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
    2240             :             // to check for errors once after all calls are made.
    2241             :             const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
    2242           0 :                     localeBundle, gNumberElementsTag, NULL, &tempStatus));
    2243             :             const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
    2244           0 :                     numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
    2245             :             const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
    2246           0 :                     nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
    2247           0 :             fTimeSeparator = ures_getUnicodeStringByKey(
    2248           0 :                     symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
    2249           0 :             if (U_FAILURE(tempStatus)) {
    2250           0 :                 fTimeSeparator.setToBogus();
    2251             :             }
    2252             :         }
    2253             : 
    2254           0 :         ures_close(localeBundle);
    2255             :     }
    2256             : 
    2257           0 :     if (fTimeSeparator.isBogus()) {
    2258           0 :         fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
    2259             :     }
    2260             : 
    2261             :     // Load day periods
    2262           0 :     fWideDayPeriods = loadDayPeriodStrings(calendarSink,
    2263             :                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
    2264             :                             fWideDayPeriodsCount, status);
    2265           0 :     fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
    2266             :                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
    2267             :                             fNarrowDayPeriodsCount, status);
    2268           0 :     fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
    2269             :                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
    2270             :                             fAbbreviatedDayPeriodsCount, status);
    2271           0 :     fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
    2272             :                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
    2273             :                             fStandaloneWideDayPeriodsCount, status);
    2274           0 :     fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
    2275             :                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
    2276             :                             fStandaloneNarrowDayPeriodsCount, status);
    2277           0 :     fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
    2278             :                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
    2279             :                             fStandaloneAbbreviatedDayPeriodsCount, status);
    2280             : 
    2281           0 :     U_LOCALE_BASED(locBased, *this);
    2282             :     // if we make it to here, the resource data is cool, and we can get everything out
    2283             :     // of it that we need except for the time-zone and localized-pattern data, which
    2284             :     // are stored in a separate file
    2285           0 :     locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
    2286           0 :                           ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
    2287             : 
    2288             :     // Load eras
    2289           0 :     initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
    2290           0 :     UErrorCode oldStatus = status;
    2291           0 :     initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
    2292           0 :     if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
    2293           0 :         status = oldStatus;
    2294           0 :         assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
    2295             :     }
    2296             :     // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
    2297           0 :     oldStatus = status;
    2298           0 :     initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
    2299           0 :     if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
    2300           0 :         status = oldStatus;
    2301           0 :         assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
    2302             :     }
    2303             : 
    2304             :     // Load month names
    2305           0 :     initField(&fMonths, fMonthsCount, calendarSink,
    2306           0 :               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
    2307           0 :     initField(&fShortMonths, fShortMonthsCount, calendarSink,
    2308           0 :               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
    2309           0 :     initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
    2310           0 :               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
    2311           0 :     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
    2312           0 :         status = U_ZERO_ERROR;
    2313           0 :         assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
    2314             :     }
    2315           0 :     initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
    2316           0 :               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
    2317           0 :     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
    2318           0 :         status = U_ZERO_ERROR;
    2319           0 :         assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
    2320             :     }
    2321             : 
    2322           0 :     UErrorCode narrowMonthsEC = status;
    2323           0 :     UErrorCode standaloneNarrowMonthsEC = status;
    2324           0 :     initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
    2325           0 :               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
    2326           0 :     initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
    2327           0 :               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
    2328           0 :     if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
    2329             :         // If format/narrow not available, use standalone/narrow
    2330           0 :         assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
    2331           0 :     } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
    2332             :         // If standalone/narrow not availabe, use format/narrow
    2333           0 :         assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
    2334           0 :     } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
    2335             :         // If neither is available, use format/abbreviated
    2336           0 :         assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
    2337           0 :         assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
    2338             :     }
    2339             : 
    2340             :     // Load AM/PM markers
    2341           0 :     initField(&fAmPms, fAmPmsCount, calendarSink,
    2342           0 :               buildResourcePath(path, gAmPmMarkersTag, status), status);
    2343           0 :     initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
    2344           0 :               buildResourcePath(path, gAmPmMarkersNarrowTag, status), status);
    2345             : 
    2346             :     // Load quarters
    2347           0 :     initField(&fQuarters, fQuartersCount, calendarSink,
    2348           0 :               buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
    2349           0 :     initField(&fShortQuarters, fShortQuartersCount, calendarSink,
    2350           0 :               buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
    2351             : 
    2352           0 :     initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
    2353           0 :               buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
    2354           0 :     if(status == U_MISSING_RESOURCE_ERROR) {
    2355           0 :         status = U_ZERO_ERROR;
    2356           0 :         assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
    2357             :     }
    2358           0 :     initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
    2359           0 :               buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
    2360           0 :     if(status == U_MISSING_RESOURCE_ERROR) {
    2361           0 :         status = U_ZERO_ERROR;
    2362           0 :         assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
    2363             :     }
    2364             : 
    2365             :     // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
    2366             :     /*
    2367             :     // fastCopyFrom()/setTo() - see assignArray comments
    2368             :     resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
    2369             :     fLocalPatternChars.setTo(TRUE, resStr, len);
    2370             :     // If the locale data does not include new pattern chars, use the defaults
    2371             :     // TODO: Consider making this an error, since this may add conflicting characters.
    2372             :     if (len < PATTERN_CHARS_LEN) {
    2373             :         fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
    2374             :     }
    2375             :     */
    2376           0 :     fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
    2377             : 
    2378             :     // Format wide weekdays -> fWeekdays
    2379             :     // {sfb} fixed to handle 1-based weekdays
    2380           0 :     initField(&fWeekdays, fWeekdaysCount, calendarSink,
    2381           0 :               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
    2382             : 
    2383             :     // Format abbreviated weekdays -> fShortWeekdays
    2384           0 :     initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
    2385           0 :               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
    2386             : 
    2387             :     // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
    2388           0 :     initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
    2389           0 :               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
    2390           0 :     if (status == U_MISSING_RESOURCE_ERROR) {
    2391           0 :         status = U_ZERO_ERROR;
    2392           0 :         assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
    2393             :     }
    2394             : 
    2395             :     // Stand-alone wide weekdays -> fStandaloneWeekdays
    2396           0 :     initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
    2397           0 :               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
    2398           0 :     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
    2399           0 :         status = U_ZERO_ERROR;
    2400           0 :         assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
    2401             :     }
    2402             : 
    2403             :     // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
    2404           0 :     initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
    2405           0 :               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
    2406           0 :     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
    2407           0 :         status = U_ZERO_ERROR;
    2408           0 :         assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
    2409             :     }
    2410             : 
    2411             :     // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
    2412           0 :     initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
    2413           0 :               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
    2414           0 :     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
    2415           0 :         status = U_ZERO_ERROR;
    2416           0 :         assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
    2417             :     }
    2418             : 
    2419             :     // Format narrow weekdays -> fNarrowWeekdays
    2420           0 :     UErrorCode narrowWeeksEC = status;
    2421           0 :     initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
    2422           0 :               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
    2423             :     // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
    2424           0 :     UErrorCode standaloneNarrowWeeksEC = status;
    2425           0 :     initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
    2426           0 :               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
    2427             : 
    2428           0 :     if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
    2429             :         // If format/narrow not available, use standalone/narrow
    2430           0 :         assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
    2431           0 :     } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
    2432             :         // If standalone/narrow not available, use format/narrow
    2433           0 :         assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
    2434           0 :     } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
    2435             :         // If neither is available, use format/abbreviated
    2436           0 :         assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
    2437           0 :         assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
    2438             :     }
    2439             : 
    2440             :     // Last resort fallback in case previous data wasn't loaded
    2441           0 :     if (U_FAILURE(status))
    2442             :     {
    2443           0 :         if (useLastResortData)
    2444             :         {
    2445             :             // Handle the case in which there is no resource data present.
    2446             :             // We don't have to generate usable patterns in this situation;
    2447             :             // we just need to produce something that will be semi-intelligible
    2448             :             // in most locales.
    2449             : 
    2450           0 :             status = U_USING_FALLBACK_WARNING;
    2451             :             //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
    2452           0 :             initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
    2453           0 :             initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
    2454           0 :             initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
    2455           0 :             initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
    2456           0 :             initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
    2457           0 :             initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
    2458           0 :             initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
    2459           0 :             initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
    2460           0 :             initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
    2461           0 :             initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2462           0 :             initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2463           0 :             initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2464           0 :             initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2465           0 :             initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2466           0 :             initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2467           0 :             initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2468           0 :             initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
    2469           0 :             initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
    2470           0 :             initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
    2471           0 :             initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
    2472           0 :             initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
    2473           0 :             initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
    2474           0 :             initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
    2475           0 :             fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
    2476             :         }
    2477             :     }
    2478             : 
    2479             :     // Close resources
    2480           0 :     ures_close(cb);
    2481           0 :     ures_close(rb);
    2482             : }
    2483             : 
    2484             : Locale
    2485           0 : DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
    2486           0 :     U_LOCALE_BASED(locBased, *this);
    2487           0 :     return locBased.getLocale(type, status);
    2488             : }
    2489             : 
    2490             : U_NAMESPACE_END
    2491             : 
    2492             : #endif /* #if !UCONFIG_NO_FORMATTING */
    2493             : 
    2494             : //eof

Generated by: LCOV version 1.13