diff options
Diffstat (limited to 'Build/source/libs/icu-xetex/i18n/dtfmtsym.cpp')
-rw-r--r-- | Build/source/libs/icu-xetex/i18n/dtfmtsym.cpp | 1225 |
1 files changed, 1095 insertions, 130 deletions
diff --git a/Build/source/libs/icu-xetex/i18n/dtfmtsym.cpp b/Build/source/libs/icu-xetex/i18n/dtfmtsym.cpp index 30ebbebcf81..b710170916f 100644 --- a/Build/source/libs/icu-xetex/i18n/dtfmtsym.cpp +++ b/Build/source/libs/icu-xetex/i18n/dtfmtsym.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 1997-2005, International Business Machines Corporation and * +* Copyright (C) 1997-2006, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* * @@ -16,6 +16,7 @@ * 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars * 03/27/00 weiv Keeping resource bundle around! * 06/30/05 emmons Added eraNames, narrow month/day, standalone context +* 10/12/05 emmons Added setters for eraNames, month/day by width/context ******************************************************************************* */ @@ -25,13 +26,16 @@ #include "unicode/dtfmtsym.h" #include "unicode/smpdtfmt.h" +#include "cpputils.h" #include "ucln_in.h" #include "mutex.h" #include "cmemory.h" #include "cstring.h" #include "locbased.h" #include "gregoimp.h" - +#include "hash.h" +#include "uresimp.h" + // ***************************************************************************** // class DateFormatSymbols // ***************************************************************************** @@ -40,19 +44,22 @@ * resource data. */ -#define PATTERN_CHARS_LEN 24 +#define PATTERN_CHARS_LEN 26 /** * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All * locales use the same these unlocalized pattern characters. */ static const UChar gPatternChars[] = { - // GyMdkHmsSEDFwWahKzYeugAZvcL + // GyMdkHmsSEDFwWahKzYeugAZvcLQq 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45, 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65, - 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0 + 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0 }; +/* length of an array */ +#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) + //------------------------------------------------------ // Strings of last resort. These are only used if we have no resource // files. They aren't designed for actual use, just for backup. @@ -78,7 +85,7 @@ static const UChar gLastResortMonthNames[13][3] = // These are the weekday names and abbreviations of last resort. static const UChar gLastResortDayNames[8][2] = { - {0x0000, 0x0000}, /* "" */ + {0x0030, 0x0000}, /* "0" */ {0x0031, 0x0000}, /* "1" */ {0x0032, 0x0000}, /* "2" */ {0x0033, 0x0000}, /* "3" */ @@ -88,6 +95,15 @@ static const UChar gLastResortDayNames[8][2] = {0x0037, 0x0000} /* "7" */ }; +// These are the quarter names and abbreviations of last resort. +static const UChar gLastResortQuarters[4][2] = +{ + {0x0031, 0x0000}, /* "1" */ + {0x0032, 0x0000}, /* "2" */ + {0x0033, 0x0000}, /* "3" */ + {0x0034, 0x0000}, /* "4" */ +}; + // These are the am/pm and BC/AD markers of last resort. static const UChar gLastResortAmPmMarkers[2][3] = { @@ -103,12 +119,14 @@ static const UChar gLastResortEras[2][3] = // These are the zone strings of last resort. -static const UChar gLastResortZoneStrings[5][4] = +static const UChar gLastResortZoneStrings[7][4] = { {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ + {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ + {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ {0x0047, 0x004D, 0x0054, 0x0000} /* "GMT" */ }; @@ -123,6 +141,9 @@ typedef enum LastResortSize { kAmPmNum = 2, kAmPmLen = 3, + kQuarterNum = 4, + kQuarterLen = 2, + kEraNum = 2, kEraLen = 3, @@ -138,22 +159,37 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols) * These are the tags we expect to see in normal resource bundle files associated * with a locale and calendar */ -const char gErasTag[]="eras"; -const char gAbbreviatedTag[] = "abbreviated"; -const char gMonthNamesTag[]="monthNames"; -const char gDayNamesTag[]="dayNames"; -const char gNamesWideTag[]="wide"; -const char gNamesAbbrTag[]="abbreviated"; -const char gNamesNarrowTag[]="narrow"; -const char gNamesStandaloneTag[]="stand-alone"; -const char gAmPmMarkersTag[]="AmPmMarkers"; +static const char gErasTag[]="eras"; +static const char gAbbreviatedTag[] = "abbreviated"; +static const char gMonthNamesTag[]="monthNames"; +static const char gDayNamesTag[]="dayNames"; +static const char gNamesWideTag[]="wide"; +static const char gNamesAbbrTag[]="abbreviated"; +static const char gNamesNarrowTag[]="narrow"; +static const char gNamesStandaloneTag[]="stand-alone"; +static const char gAmPmMarkersTag[]="AmPmMarkers"; +static const char gQuartersTag[]="quarters"; /** * These are the tags we expect to see in time zone data resource bundle files * associated with a locale. */ -const char gZoneStringsTag[]="zoneStrings"; -const char gLocalPatternCharsTag[]="localPatternChars"; +static const char gZoneStringsTag[]="zoneStrings"; +static const char gLocalPatternCharsTag[]="localPatternChars"; + +static UMTX LOCK; + +/* + * Keep this variable in synch with max length of display strings + */ +#define UTZ_MAX_DISPLAY_STRINGS_LENGTH 7 +#define UTZ_SHORT_GENERIC "sg" +#define UTZ_SHORT_STANDARD "ss" +#define UTZ_SHORT_DAYLIGHT "sd" +#define UTZ_LONG_GENERIC "lg" +#define UTZ_LONG_STANDARD "ls" +#define UTZ_LONG_DAYLIGHT "ld" +#define UTZ_EXEMPLAR_CITY "ec" /** * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly. @@ -163,6 +199,12 @@ static inline UnicodeString* newUnicodeStringArray(size_t count) { return new UnicodeString[count ? count : 1]; } +U_CDECL_BEGIN +static void deleteUnicodeStringArray(void* obj) { + delete[] (UnicodeString*)obj; +} +U_CDECL_END + //------------------------------------------------------ DateFormatSymbols::DateFormatSymbols(const Locale& locale, @@ -268,10 +310,29 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) { assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount); assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount); assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount); - - fZoneStringsRowCount = other.fZoneStringsRowCount; - fZoneStringsColCount = other.fZoneStringsColCount; - createZoneStrings((const UnicodeString**)other.fZoneStrings); + assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount); + assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount); + assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount); + assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount); + // the zoneStrings data is initialized on demand + //fZoneStringsRowCount = other.fZoneStringsRowCount; + //fZoneStringsColCount = other.fZoneStringsColCount; + //createZoneStrings((const UnicodeString**)other.fZoneStrings); + // initialize on demand + fZoneStringsHash = NULL; + fZoneIDEnumeration = NULL; + fZoneStrings = NULL; + fZoneStringsColCount = 0; + fZoneStringsRowCount = 0; + fResourceBundle = NULL; + if(other.fZoneStringsHash!=NULL){ + fZoneStringsHash = createZoneStringsHash(other.fZoneStringsHash); + fZoneIDEnumeration = other.fZoneIDEnumeration->clone(); + }else{ + UErrorCode status =U_ZERO_ERROR; + fResourceBundle = ures_clone(other.fResourceBundle, &status); + // TODO: what should be done in case of error? + } // fastCopyFrom() - see assignArray comments fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars); @@ -310,6 +371,10 @@ void DateFormatSymbols::dispose() if (fStandaloneShortWeekdays) delete[] fStandaloneShortWeekdays; if (fStandaloneNarrowWeekdays) delete[] fStandaloneNarrowWeekdays; if (fAmPms) delete[] fAmPms; + if (fQuarters) delete[] fQuarters; + if (fShortQuarters) delete[] fShortQuarters; + if (fStandaloneQuarters) delete[] fStandaloneQuarters; + if (fStandaloneShortQuarters) delete[] fStandaloneShortQuarters; disposeZoneStrings(); } @@ -320,7 +385,17 @@ void DateFormatSymbols::disposeZoneStrings() for (int32_t row=0; row<fZoneStringsRowCount; ++row) delete[] fZoneStrings[row]; uprv_free(fZoneStrings); + } + if(fZoneStringsHash){ + delete fZoneStringsHash; + fZoneStringsHash = NULL; } + if(fZoneIDEnumeration){ + delete fZoneIDEnumeration; + fZoneIDEnumeration = NULL; + } + ures_close(fResourceBundle); + fResourceBundle = NULL; } UBool @@ -359,8 +434,10 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount && fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount && fAmPmsCount == other.fAmPmsCount && - fZoneStringsRowCount == other.fZoneStringsRowCount && - fZoneStringsColCount == other.fZoneStringsColCount) + fQuartersCount == other.fQuartersCount && + fShortQuartersCount == other.fShortQuartersCount && + fStandaloneQuartersCount == other.fStandaloneQuartersCount && + fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount) { // Now compare the arrays themselves if (arrayCompare(fEras, other.fEras, fErasCount) && @@ -377,15 +454,28 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) && arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) && arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) && - arrayCompare(fAmPms, other.fAmPms, fAmPmsCount)) + arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) && + arrayCompare(fQuarters, other.fQuarters, fQuartersCount) && + arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) && + arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) && + arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount)) { - if (fZoneStrings == other.fZoneStrings) return TRUE; - - for (int32_t row=0; row<fZoneStringsRowCount; ++row) - { - if (!arrayCompare(fZoneStrings[row], other.fZoneStrings[row], fZoneStringsColCount)) + + if(fZoneStringsHash == NULL || other.fZoneStringsHash == NULL){ + // fZoneStringsHash is not initialized compare the resource bundles + if(ures_equal(fResourceBundle, other.fResourceBundle)== FALSE){ + return FALSE; + } + }else{ + if(fZoneStringsHash->equals(*other.fZoneStringsHash) == FALSE){ return FALSE; + } + // we always make sure that we update the enumeration when the hash is + // updated. So we can be sure that once we compare the hashes the + // enumerations are also equal } + // since fZoneStrings data member is deprecated .. and may not be initialized + // so don't compare them return TRUE; } } @@ -428,38 +518,44 @@ DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType UnicodeString *returnValue = NULL; switch (context) { - case FORMAT : - switch(width) { - case WIDE : - count = fMonthsCount; - returnValue = fMonths; - break; - case ABBREVIATED : - count = fShortMonthsCount; - returnValue = fShortMonths; - break; - case NARROW : - count = fNarrowMonthsCount; - returnValue = fNarrowMonths; - break; - } - break; - case STANDALONE : - switch(width) { - case WIDE : - count = fStandaloneMonthsCount; - returnValue = fStandaloneMonths; - break; - case ABBREVIATED : - count = fStandaloneShortMonthsCount; - returnValue = fStandaloneShortMonths; - break; - case NARROW : - count = fStandaloneNarrowMonthsCount; - returnValue = fStandaloneNarrowMonths; - break; - } - break; + case FORMAT : + switch(width) { + case WIDE : + count = fMonthsCount; + returnValue = fMonths; + break; + case ABBREVIATED : + count = fShortMonthsCount; + returnValue = fShortMonths; + break; + case NARROW : + count = fNarrowMonthsCount; + returnValue = fNarrowMonths; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case STANDALONE : + switch(width) { + case WIDE : + count = fStandaloneMonthsCount; + returnValue = fStandaloneMonths; + break; + case ABBREVIATED : + count = fStandaloneShortMonthsCount; + returnValue = fStandaloneShortMonths; + break; + case NARROW : + count = fStandaloneNarrowMonthsCount; + returnValue = fStandaloneNarrowMonths; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case DT_CONTEXT_COUNT : + break; } return returnValue; } @@ -483,38 +579,92 @@ DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthTyp { UnicodeString *returnValue = NULL; switch (context) { - case FORMAT : - switch(width) { - case WIDE : + case FORMAT : + switch(width) { + case WIDE : count = fWeekdaysCount; returnValue = fWeekdays; break; - case ABBREVIATED : + case ABBREVIATED : count = fShortWeekdaysCount; returnValue = fShortWeekdays; break; - case NARROW : + case NARROW : count = fNarrowWeekdaysCount; returnValue = fNarrowWeekdays; break; - } - break; - case STANDALONE : - switch(width) { - case WIDE : + case DT_WIDTH_COUNT : + break; + } + break; + case STANDALONE : + switch(width) { + case WIDE : count = fStandaloneWeekdaysCount; returnValue = fStandaloneWeekdays; break; - case ABBREVIATED : + case ABBREVIATED : count = fStandaloneShortWeekdaysCount; returnValue = fStandaloneShortWeekdays; break; - case NARROW : + case NARROW : count = fStandaloneNarrowWeekdaysCount; returnValue = fStandaloneNarrowWeekdays; break; - } - break; + case DT_WIDTH_COUNT : + break; + } + break; + case DT_CONTEXT_COUNT : + break; + } + return returnValue; +} + +const UnicodeString* +DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const +{ + UnicodeString *returnValue = NULL; + + switch (context) { + case FORMAT : + switch(width) { + case WIDE : + count = fQuartersCount; + returnValue = fQuarters; + break; + case ABBREVIATED : + count = fShortQuartersCount; + returnValue = fShortQuarters; + break; + case NARROW : + count = 0; + returnValue = NULL; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case STANDALONE : + switch(width) { + case WIDE : + count = fStandaloneQuartersCount; + returnValue = fStandaloneQuarters; + break; + case ABBREVIATED : + count = fStandaloneShortQuartersCount; + returnValue = fStandaloneShortQuarters; + break; + case NARROW : + count = 0; + returnValue = NULL; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case DT_CONTEXT_COUNT : + break; } return returnValue; } @@ -532,7 +682,8 @@ void DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count) { // delete the old list if we own it - if (fEras) delete[] fEras; + if (fEras) + delete[] fEras; // we always own the new list, which we create here (we duplicate rather // than adopting the list passed in) @@ -542,10 +693,25 @@ DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count) } void +DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count) +{ + // delete the old list if we own it + if (fEraNames) + delete[] fEraNames; + + // we always own the new list, which we create here (we duplicate rather + // than adopting the list passed in) + fEraNames = newUnicodeStringArray(count); + uprv_arrayCopy(eraNamesArray,fEraNames, count); + fEraNamesCount = count; +} + +void DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count) { // delete the old list if we own it - if (fMonths) delete[] fMonths; + if (fMonths) + delete[] fMonths; // we always own the new list, which we create here (we duplicate rather // than adopting the list passed in) @@ -558,7 +724,8 @@ void DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count) { // delete the old list if we own it - if (fShortMonths) delete[] fShortMonths; + if (fShortMonths) + delete[] fShortMonths; // we always own the new list, which we create here (we duplicate rather // than adopting the list passed in) @@ -567,10 +734,78 @@ DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t fShortMonthsCount = count; } +void +DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width) +{ + // delete the old list if we own it + // we always own the new list, which we create here (we duplicate rather + // than adopting the list passed in) + + switch (context) { + case FORMAT : + switch (width) { + case WIDE : + if (fMonths) + delete[] fMonths; + fMonths = newUnicodeStringArray(count); + uprv_arrayCopy( monthsArray,fMonths,count); + fMonthsCount = count; + break; + case ABBREVIATED : + if (fShortMonths) + delete[] fShortMonths; + fShortMonths = newUnicodeStringArray(count); + uprv_arrayCopy( monthsArray,fShortMonths,count); + fShortMonthsCount = count; + break; + case NARROW : + if (fNarrowMonths) + delete[] fNarrowMonths; + fNarrowMonths = newUnicodeStringArray(count); + uprv_arrayCopy( monthsArray,fNarrowMonths,count); + fNarrowMonthsCount = count; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case STANDALONE : + switch (width) { + case WIDE : + if (fStandaloneMonths) + delete[] fStandaloneMonths; + fStandaloneMonths = newUnicodeStringArray(count); + uprv_arrayCopy( monthsArray,fStandaloneMonths,count); + fStandaloneMonthsCount = count; + break; + case ABBREVIATED : + if (fStandaloneShortMonths) + delete[] fStandaloneShortMonths; + fStandaloneShortMonths = newUnicodeStringArray(count); + uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count); + fStandaloneShortMonthsCount = count; + break; + case NARROW : + if (fStandaloneNarrowMonths) + delete[] fStandaloneNarrowMonths; + fStandaloneNarrowMonths = newUnicodeStringArray(count); + uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count); + fStandaloneNarrowMonthsCount = count; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case DT_CONTEXT_COUNT : + break; + } +} + void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count) { // delete the old list if we own it - if (fWeekdays) delete[] fWeekdays; + if (fWeekdays) + delete[] fWeekdays; // we always own the new list, which we create here (we duplicate rather // than adopting the list passed in) @@ -583,16 +818,155 @@ void DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count) { // delete the old list if we own it - if (fShortWeekdays) delete[] fShortWeekdays; + if (fShortWeekdays) + delete[] fShortWeekdays; // we always own the new list, which we create here (we duplicate rather // than adopting the list passed in) fShortWeekdays = newUnicodeStringArray(count); - uprv_arrayCopy( shortWeekdaysArray,fShortWeekdays,count); + uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count); fShortWeekdaysCount = count; } void +DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width) +{ + // delete the old list if we own it + // we always own the new list, which we create here (we duplicate rather + // than adopting the list passed in) + + switch (context) { + case FORMAT : + switch (width) { + case WIDE : + if (fWeekdays) + delete[] fWeekdays; + fWeekdays = newUnicodeStringArray(count); + uprv_arrayCopy(weekdaysArray, fWeekdays, count); + fWeekdaysCount = count; + break; + case ABBREVIATED : + if (fShortWeekdays) + delete[] fShortWeekdays; + fShortWeekdays = newUnicodeStringArray(count); + uprv_arrayCopy(weekdaysArray, fShortWeekdays, count); + fShortWeekdaysCount = count; + break; + case NARROW : + if (fNarrowWeekdays) + delete[] fNarrowWeekdays; + fNarrowWeekdays = newUnicodeStringArray(count); + uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count); + fNarrowWeekdaysCount = count; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case STANDALONE : + switch (width) { + case WIDE : + if (fStandaloneWeekdays) + delete[] fStandaloneWeekdays; + fStandaloneWeekdays = newUnicodeStringArray(count); + uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count); + fStandaloneWeekdaysCount = count; + break; + case ABBREVIATED : + if (fStandaloneShortWeekdays) + delete[] fStandaloneShortWeekdays; + fStandaloneShortWeekdays = newUnicodeStringArray(count); + uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count); + fStandaloneShortWeekdaysCount = count; + break; + case NARROW : + if (fStandaloneNarrowWeekdays) + delete[] fStandaloneNarrowWeekdays; + fStandaloneNarrowWeekdays = newUnicodeStringArray(count); + uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count); + fStandaloneNarrowWeekdaysCount = count; + break; + case DT_WIDTH_COUNT : + break; + } + break; + case DT_CONTEXT_COUNT : + break; + } +} + +void +DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width) +{ + // delete the old list if we own it + // we always own the new list, which we create here (we duplicate rather + // than adopting the list passed in) + + switch (context) { + case FORMAT : + switch (width) { + case WIDE : + if (fQuarters) + delete[] fQuarters; + fQuarters = newUnicodeStringArray(count); + uprv_arrayCopy( quartersArray,fQuarters,count); + fQuartersCount = count; + break; + case ABBREVIATED : + if (fShortQuarters) + delete[] fShortQuarters; + fShortQuarters = newUnicodeStringArray(count); + uprv_arrayCopy( quartersArray,fShortQuarters,count); + fShortQuartersCount = count; + break; + case NARROW : + /* + if (fNarrowQuarters) + delete[] fNarrowQuarters; + fNarrowQuarters = newUnicodeStringArray(count); + uprv_arrayCopy( quartersArray,fNarrowQuarters,count); + fNarrowQuartersCount = count; + */ + break; + case DT_WIDTH_COUNT : + break; + } + break; + case STANDALONE : + switch (width) { + case WIDE : + if (fStandaloneQuarters) + delete[] fStandaloneQuarters; + fStandaloneQuarters = newUnicodeStringArray(count); + uprv_arrayCopy( quartersArray,fStandaloneQuarters,count); + fStandaloneQuartersCount = count; + break; + case ABBREVIATED : + if (fStandaloneShortQuarters) + delete[] fStandaloneShortQuarters; + fStandaloneShortQuarters = newUnicodeStringArray(count); + uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count); + fStandaloneShortQuartersCount = count; + break; + case NARROW : + /* + if (fStandaloneNarrowQuarters) + delete[] fStandaloneNarrowQuarters; + fStandaloneNarrowQuarters = newUnicodeStringArray(count); + uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count); + fStandaloneNarrowQuartersCount = count; + */ + break; + case DT_WIDTH_COUNT : + break; + } + break; + case DT_CONTEXT_COUNT : + break; + } +} + +void DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count) { // delete the old list if we own it @@ -610,8 +984,18 @@ DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count const UnicodeString** DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const { + umtx_lock(&LOCK); + UErrorCode status = U_ZERO_ERROR; + if(fZoneStrings==NULL){ + // cast away const to get around the problem for lazy initialization + ((DateFormatSymbols*)this)->initZoneStringsArray(status); + if(U_FAILURE(status)){ + return NULL; + } + } rowCount = fZoneStringsRowCount; columnCount = fZoneStringsColCount; + umtx_unlock(&LOCK); return (const UnicodeString**)fZoneStrings; // Compiler requires cast } @@ -621,12 +1005,13 @@ DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t r // since deleting a 2-d array is a pain in the butt, we offload that task to // a separate function disposeZoneStrings(); - + UErrorCode status = U_ZERO_ERROR; // we always own the new list, which we create here (we duplicate rather // than adopting the list passed in) fZoneStringsRowCount = rowCount; fZoneStringsColCount = columnCount; createZoneStrings((const UnicodeString**)strings); + initZoneStrings((const UnicodeString**)strings, rowCount,columnCount, status); } //------------------------------------------------------ @@ -701,7 +1086,6 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError int32_t i; int32_t len = 0; const UChar *resStr; - /* In case something goes wrong, initialize all of the data to NULL. */ fEras = NULL; fErasCount = 0; @@ -733,11 +1117,22 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError fStandaloneNarrowWeekdaysCount=0; fAmPms = NULL; fAmPmsCount=0; + fQuarters = NULL; + fQuartersCount = 0; + fShortQuarters = NULL; + fShortQuartersCount = 0; + fStandaloneQuarters = NULL; + fStandaloneQuartersCount = 0; + fStandaloneShortQuarters = NULL; + fStandaloneShortQuartersCount = 0; fZoneStringsRowCount = 0; fZoneStringsColCount = 0; fZoneStrings = NULL; - - + fZoneStringsHash = NULL; + fZoneIDEnumeration = NULL; + fResourceBundle = NULL; + + if (U_FAILURE(status)) return; /** @@ -746,7 +1141,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError * these. */ CalendarData calData(locale, type, status); - UResourceBundle *nonCalendarData = ures_open((char*)0, locale.getName(), &status); + fResourceBundle = ures_open((char*)0, locale.getName(), &status); // load the first data item UResourceBundle *erasMain = calData.getByKey(gErasTag, status); @@ -764,8 +1159,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError UResourceBundle *standaloneWeekdaysData = NULL; // Data closed by calData UResourceBundle *standaloneShortWeekdaysData = NULL; // Data closed by calData UResourceBundle *standaloneNarrowWeekdaysData = NULL; // Data closed by calData - UResourceBundle *zoneArray = ures_getByKey(nonCalendarData, gZoneStringsTag, NULL, &status); - UResourceBundle *zoneRow = ures_getByIndex(zoneArray, (int32_t)0, NULL, &status); + U_LOCALE_BASED(locBased, *this); if (U_FAILURE(status)) { @@ -793,14 +1187,10 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status); - - fZoneStrings = (UnicodeString **)uprv_malloc(sizeof(UnicodeString *)); - /* test for NULL */ - if (fZoneStrings == 0) { - status = U_MEMORY_ALLOCATION_ERROR; - } - fZoneStringsRowCount = 1; - initField(fZoneStrings, fZoneStringsColCount, (const UChar *)gLastResortZoneStrings, kZoneNum, kZoneLen, status); + initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); + initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); + initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); + initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); fLocalPatternChars = gPatternChars; } goto cleanup; @@ -811,15 +1201,23 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError // are stored in a separate file locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status), ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status)); + initField(&fEras, fErasCount, eras, status); initField(&fEraNames, fEraNamesCount, eraNames, status); + initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status); initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); + initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status); + if(status == U_MISSING_RESOURCE_ERROR) { + status = U_ZERO_ERROR; + initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status); + } if ( status == U_MISSING_RESOURCE_ERROR ) { /* If format/narrow not available, use format/abbreviated */ status = U_ZERO_ERROR; initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); } + initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status); if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/wide not available, use format/wide */ status = U_ZERO_ERROR; @@ -841,8 +1239,23 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError } initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status); + initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status); + initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status); + + initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status); + if(status == U_MISSING_RESOURCE_ERROR) { + status = U_ZERO_ERROR; + initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status); + } + + initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status); + if(status == U_MISSING_RESOURCE_ERROR) { + status = U_ZERO_ERROR; + initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status); + } + // fastCopyFrom()/setTo() - see assignArray comments - resStr = ures_getStringByKey(nonCalendarData, gLocalPatternCharsTag, &len, &status); + resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status); fLocalPatternChars.setTo(TRUE, resStr, len); // If the locale data does not include new pattern chars, use the defaults // TODO: Consider making this an error, since this may add conflicting characters. @@ -850,39 +1263,12 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len)); } - /* TODO: Fix the case where the zoneStrings is not a perfect square array of information. */ - fZoneStringsRowCount = ures_getSize(zoneArray); - fZoneStringsColCount = ures_getSize(zoneRow); - fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *)); - /* test for NULL */ - if (fZoneStrings == 0) { - status = U_MEMORY_ALLOCATION_ERROR; - goto cleanup; - } - for(i = 0; i<fZoneStringsRowCount; i++) { - *(fZoneStrings+i) = newUnicodeStringArray(fZoneStringsColCount); - /* test for NULL */ - if ((*(fZoneStrings+i)) == 0) { - status = U_MEMORY_ALLOCATION_ERROR; - goto cleanup; - } - zoneRow = ures_getByIndex(zoneArray, i, zoneRow, &status); - // compute the size of the array dynamically. Don't assume - // that all rows of zone strings are of the same size. - int32_t size = ures_getSize(zoneRow); - for(int32_t j = 0; j<size; j++) { - resStr = ures_getStringByIndex(zoneRow, j, &len, &status); - // setTo() - see assignArray comments - fZoneStrings[i][j].setTo(TRUE, resStr, len); - } - } - // {sfb} fixed to handle 1-based weekdays weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status); fWeekdaysCount = ures_getSize(weekdaysData); fWeekdays = new UnicodeString[fWeekdaysCount+1]; - /* test for NULL */ - if (fWeekdays == 0) { + /* pin the blame on system. If we cannot get a chunk of memory .. the system is dying!*/ + if (fWeekdays == NULL) { status = U_MEMORY_ALLOCATION_ERROR; goto cleanup; } @@ -911,6 +1297,10 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError fShortWeekdaysCount++; narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status); + if(status == U_MISSING_RESOURCE_ERROR) { + status = U_ZERO_ERROR; + narrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status); + } if ( status == U_MISSING_RESOURCE_ERROR ) { status = U_ZERO_ERROR; narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status); @@ -997,9 +1387,6 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError cleanup: ures_close(eras); ures_close(eraNames); - ures_close(zoneRow); - ures_close(zoneArray); - ures_close(nonCalendarData); } /** @@ -1057,6 +1444,584 @@ DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const return locBased.getLocale(type, status); } +class TimeZoneKeysEnumeration : public StringEnumeration { +private: + UnicodeString* strings; + int32_t length; + int32_t current; + int32_t capacity; + TimeZoneKeysEnumeration(UnicodeString* oldStrs, int32_t count){ + strings = newUnicodeStringArray(count); + if(strings==NULL){ + return; + } + capacity = count; + current = 0; + for(length = 0; length<capacity; length++){ + strings[length].setTo(oldStrs[length]); + } + } +public: + static UClassID U_EXPORT2 getStaticClassID(void); + virtual UClassID getDynamicClassID(void) const; + + TimeZoneKeysEnumeration(int32_t count, UErrorCode status){ + strings = newUnicodeStringArray(count); + if(strings == NULL){ + status = U_MEMORY_ALLOCATION_ERROR; + } + length = 0; + current = 0; + capacity = count; + } + + void put(const UnicodeString& str, UErrorCode& status){ + if(length < capacity){ + strings[length++].setTo(str); + }else{ + status = U_INDEX_OUTOFBOUNDS_ERROR; + } + } + virtual ~TimeZoneKeysEnumeration() { + delete[] strings; + } + + virtual StringEnumeration * clone() const + { + return new TimeZoneKeysEnumeration(strings, length); + } + + virtual int32_t count(UErrorCode &/*status*/) const { + return length; + } + virtual const UChar* unext(int32_t *resultLength, UErrorCode& /*status*/){ + if(current < length){ + const UChar* ret = strings[current].getBuffer(); + *resultLength = strings[current].length(); + current++; + return ret; + } + return NULL; + } + + virtual const UnicodeString* snext(UErrorCode& status) { + if(U_FAILURE(status)){ + return NULL; + } + if(current < length){ + return &strings[current++]; + } + return NULL; + } + /* this method is for thread safe iteration */ + const UnicodeString* snext(int32_t& pos, UErrorCode& status)const { + if(U_FAILURE(status)){ + return NULL; + } + if(pos < length){ + return &strings[pos++]; + } + return NULL; + } + + virtual void reset(UErrorCode& /*status*/) { + current = 0; + + } +private: + UBool equals(const StringEnumeration& other) const{ + if (other.getDynamicClassID() != TimeZoneKeysEnumeration::getStaticClassID()) { + return FALSE; + } + TimeZoneKeysEnumeration& enum2 = (TimeZoneKeysEnumeration&)(other); + UErrorCode status = U_ZERO_ERROR; + + int32_t count1 = count(status); + int32_t count2 = other.count(status); + if(count1 != count2){ + return FALSE; + } + int32_t pos1 = 0; + int32_t pos2 = 0; + const UnicodeString* str1 = NULL; + const UnicodeString* str2 = NULL; + + while((str1 = snext(pos1, status))!=NULL){ + str2 = enum2.snext(pos2, status); + if(U_FAILURE(status)){ + return FALSE; + } + if(*str1 != *str2){ + // bail out at the first failure + return FALSE; + } + + } + // if we reached here that means that the enumerations are equal + return TRUE; + } +public: + virtual UBool operator==(const StringEnumeration& that)const{ + return ((this == &that) || + (getDynamicClassID() == that.getDynamicClassID() && + StringEnumeration::operator==(that) && + equals(that))); + } +}; + +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeZoneKeysEnumeration) + +void +DateFormatSymbols::initZoneStringsArray(UErrorCode& status){ + if(fZoneStringsHash == NULL){ + initZoneStrings(status); + } + if(U_FAILURE(status)){ + return; + } + fZoneStringsRowCount = fZoneIDEnumeration->count(status); + fZoneStringsColCount = 8; + fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *)); + /* if we can't get a chunk of heap then the system is going down. Pin the blame on system*/ + if (fZoneStrings == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + const UnicodeString *zid = NULL; + TimeZoneKeysEnumeration *keys = (TimeZoneKeysEnumeration*) fZoneIDEnumeration; + int32_t pos = 0; + int32_t i = 0; + while((zid=keys->snext(pos,status))!=NULL){ + *(fZoneStrings+i) = newUnicodeStringArray(fZoneStringsColCount); + /* test for NULL */ + if ((*(fZoneStrings+i)) == 0) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(*zid); + fZoneStrings[i][0].setTo(*zid); + fZoneStrings[i][1].setTo(strings[TIMEZONE_LONG_STANDARD]); + fZoneStrings[i][2].setTo(strings[TIMEZONE_SHORT_STANDARD]); + fZoneStrings[i][3].setTo(strings[TIMEZONE_LONG_DAYLIGHT]); + fZoneStrings[i][4].setTo(strings[TIMEZONE_SHORT_DAYLIGHT]); + fZoneStrings[i][5].setTo(strings[TIMEZONE_EXEMPLAR_CITY]); + if(fZoneStrings[i][5].length()==0){ + fZoneStrings[i][5].setTo(strings[TIMEZONE_LONG_GENERIC]); + }else{ + fZoneStrings[i][6].setTo(strings[TIMEZONE_LONG_GENERIC]); + } + if(fZoneStrings[i][6].length()==0){ + fZoneStrings[i][6].setTo(strings[TIMEZONE_LONG_GENERIC]); + }else{ + fZoneStrings[i][7].setTo(strings[TIMEZONE_LONG_GENERIC]); + } + i++; + } +} + +U_CDECL_BEGIN +static UBool U_CALLCONV +compareTZHashValues(const UHashTok val1, const UHashTok val2){ + + const UnicodeString* array1 = (UnicodeString*) val1.pointer; + const UnicodeString* array2 = (UnicodeString*) val2.pointer; + if(array1==array2){ + return TRUE; + } + if(array1==NULL || array2==NULL){ + return FALSE; + } + for(int32_t j=0; j< UTZ_MAX_DISPLAY_STRINGS_LENGTH; j++){ + if(array1[j] != array2[j]){ + return FALSE; + } + } + return TRUE; +} +U_CDECL_END + +void +DateFormatSymbols::initZoneStrings(UErrorCode &status){ + if(U_FAILURE(status)){ + return; + } + + if(fZoneStringsHash != NULL){ + return; + } + int32_t i; + + fZoneStringsHash = new Hashtable(uhash_compareUnicodeString, compareTZHashValues, status); + if(fZoneStringsHash==NULL){ + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + fZoneStringsHash->setValueDeleter(deleteUnicodeStringArray); + + if(fResourceBundle != NULL){ + UnicodeString solidus = UNICODE_STRING_SIMPLE("/"); + UnicodeString colon = UNICODE_STRING_SIMPLE(":"); + UResourceBundle zoneArray,zoneItem; + ures_initStackObject(&zoneItem); + ures_initStackObject(&zoneArray); + for(const UResourceBundle* rb = fResourceBundle; rb!=NULL; rb=ures_getParentBundle(rb)){ + ures_getByKey(rb, gZoneStringsTag, &zoneArray, &status); + if(U_FAILURE(status)){ + break; + } + while(ures_hasNext(&zoneArray)){ + UErrorCode tempStatus = U_ZERO_ERROR; + UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH); + ures_getNextResource(&zoneArray, &zoneItem, &status); + UnicodeString key(ures_getKey(&zoneItem), -1, US_INV); + key.findAndReplace(colon, solidus); + int32_t len = 0; + //fetch the strings with fine grained fallback + const UChar* str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_SHORT_STANDARD, &len, &tempStatus); + if(U_SUCCESS(tempStatus)){ + array[TIMEZONE_SHORT_STANDARD].setTo(TRUE, str, len); + }else{ + tempStatus = U_ZERO_ERROR; + } + str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_SHORT_GENERIC, &len, &tempStatus); + if(U_SUCCESS(tempStatus)){ + array[TIMEZONE_SHORT_GENERIC].setTo(TRUE, str, len); + }else{ + tempStatus = U_ZERO_ERROR; + } + str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_SHORT_DAYLIGHT, &len, &tempStatus); + if(U_SUCCESS(tempStatus)){ + array[TIMEZONE_SHORT_DAYLIGHT].setTo(TRUE, str, len); + }else{ + tempStatus = U_ZERO_ERROR; + } + str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_LONG_STANDARD, &len, &tempStatus); + if(U_SUCCESS(tempStatus)){ + array[TIMEZONE_LONG_STANDARD].setTo(TRUE, str, len); + }else{ + tempStatus = U_ZERO_ERROR; + } + str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_LONG_GENERIC, &len, &tempStatus); + if(U_SUCCESS(tempStatus)){ + array[TIMEZONE_LONG_GENERIC].setTo(TRUE, str, len); + }else{ + tempStatus = U_ZERO_ERROR; + } + str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_LONG_DAYLIGHT, &len, &tempStatus); + if(U_SUCCESS(tempStatus)){ + array[TIMEZONE_LONG_DAYLIGHT].setTo(TRUE, str, len); + }else{ + tempStatus = U_ZERO_ERROR; + } + str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_EXEMPLAR_CITY, &len, &tempStatus); + if(U_SUCCESS(tempStatus)){ + array[TIMEZONE_EXEMPLAR_CITY].setTo(TRUE, str, len); + }else{ + tempStatus = U_ZERO_ERROR; + } + // store the strings in hash + fZoneStringsHash->put(key, array, status); + } + ures_close(&zoneItem); + ures_close(&zoneArray); + } + int32_t length = fZoneStringsHash->count(); + TimeZoneKeysEnumeration* keysEnum = new TimeZoneKeysEnumeration(length, status); + fZoneIDEnumeration = keysEnum; + if(fZoneIDEnumeration==NULL){ + delete fZoneStringsHash; + fZoneStringsHash = NULL; + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + int32_t pos=-1; + const UnicodeString* key; + const UHashElement* elem = NULL; + while((elem = fZoneStringsHash->nextElement(pos))!= NULL){ + const UHashTok keyTok = elem->key; + key = (const UnicodeString*)keyTok.pointer; + keysEnum->put(*key, status); + } + }else{ + //last resort strings + UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH); + if(array==NULL){ + delete fZoneStringsHash; + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + int32_t length = ARRAY_LENGTH(gLastResortZoneStrings); + UnicodeString key(gLastResortZoneStrings[0]); + TimeZoneKeysEnumeration* keysEnum = new TimeZoneKeysEnumeration(length, status); + fZoneIDEnumeration = keysEnum; + if(fZoneIDEnumeration==NULL){ + delete fZoneStringsHash; + delete[] array; + fZoneStringsHash = NULL; + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + keysEnum->put(key, status); + int32_t j=1; + for(i=0; i< length; ){ + array[i++].setTo(gLastResortZoneStrings[j++]); + } + fZoneStringsHash->put(key, array, status); + } +} +void +DateFormatSymbols::initZoneStrings(const UnicodeString** strings, int32_t rowCount, int32_t columnCount, UErrorCode& status){ + if(strings==NULL || rowCount<0 || columnCount<0){ + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + TimeZoneKeysEnumeration* keysEnum = new TimeZoneKeysEnumeration(rowCount, status); + fZoneIDEnumeration = keysEnum; + if(U_FAILURE(status)){ + return; + } + if(fZoneIDEnumeration==NULL){ + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + fZoneStringsHash = new Hashtable(uhash_compareUnicodeString, compareTZHashValues, status); + if(U_FAILURE(status)){ + return; + } + if(fZoneStringsHash==NULL){ + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + fZoneStringsHash->setValueDeleter(deleteUnicodeStringArray); + for (int32_t row=0; row<rowCount; ++row){ + // the first string in the array is the key. + UnicodeString key = strings[row][0]; + keysEnum->put(key, status); + UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH); + if(array==NULL){ + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + for (int32_t col=1; col<columnCount; ++col) { + // fastCopyFrom() - see assignArray comments + switch (col){ + case 1: + array[TIMEZONE_LONG_STANDARD].setTo(strings[row][col]); + break; + case 2: + array[TIMEZONE_SHORT_STANDARD].setTo(strings[row][col]); + break; + case 3: + array[TIMEZONE_LONG_DAYLIGHT].setTo(strings[row][col]); + break; + case 4: + array[TIMEZONE_LONG_DAYLIGHT].setTo(strings[row][col]); + break; + case 5: + if(fZoneStringsColCount==6 || fZoneStringsColCount==8){ + array[TIMEZONE_EXEMPLAR_CITY].setTo(strings[row][col]); + }else{ + array[TIMEZONE_LONG_GENERIC].setTo(strings[row][col]); + } + break; + case 6: + if(fZoneStringsColCount==8){ + array[TIMEZONE_LONG_GENERIC].setTo(strings[row][col]); + }else{ + array[TIMEZONE_SHORT_GENERIC].setTo(strings[row][col]); + } + break; + case 7: + array[TIMEZONE_SHORT_GENERIC].setTo(strings[row][col]); + break; + default: + status = U_ILLEGAL_ARGUMENT_ERROR; + } + // populate the hash table + fZoneStringsHash->put(strings[row][0], array, status); + } + } + +} + +UnicodeString& +DateFormatSymbols::getZoneString(const UnicodeString &zid, const TimeZoneTranslationType type, + UnicodeString &result, UErrorCode &status){ + + if(fZoneStringsHash == NULL){ + //lazy initialization + initZoneStrings(status); + } + if(U_FAILURE(status)){ + return result; + } + UnicodeString* stringsArray = (UnicodeString*)fZoneStringsHash->get(zid); + if(stringsArray != NULL){ + result.setTo(stringsArray[type],0); + } + + return result; +} + +StringEnumeration* +DateFormatSymbols::createZoneStringIDs(UErrorCode &status){ + if(U_FAILURE(status)){ + return NULL; + } + if(fZoneStringsHash == NULL){ + //lazy initialization + initZoneStrings(status); + } + return fZoneIDEnumeration->clone(); +} + +/** + * Sets timezone strings. + * @draft ICU 3.6 + */ +void +DateFormatSymbols::setZoneString(const UnicodeString &zid, const TimeZoneTranslationType type, + const UnicodeString &value, UErrorCode &status){ + if(fZoneStringsHash == NULL){ + //lazy initialization + initZoneStrings(status); + } + if(U_FAILURE(status)){ + return; + } + UnicodeString* stringsArray = (UnicodeString*)fZoneStringsHash->get(zid); + if(stringsArray != NULL){ + stringsArray[type].setTo(value); + }else{ + stringsArray = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH); + if(stringsArray==NULL){ + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + stringsArray[type].setTo(value); + fZoneStringsHash->put(zid, stringsArray, status); + TimeZoneKeysEnumeration* keys = (TimeZoneKeysEnumeration*) fZoneIDEnumeration; + keys->put(zid, status); + } +} + +Hashtable* +DateFormatSymbols::createZoneStringsHash(const Hashtable* otherHash){ + UErrorCode status = U_ZERO_ERROR; + Hashtable* hash = new Hashtable(uhash_compareUnicodeString, compareTZHashValues, status); + if(hash==NULL){ + return NULL; + } + if(U_FAILURE(status)){ + return NULL; + } + hash->setValueDeleter(deleteUnicodeStringArray); + int32_t pos = -1; + const UHashElement* elem = NULL; + // walk through the hash table and create a deep clone + while((elem = otherHash->nextElement(pos))!= NULL){ + const UHashTok otherKeyTok = elem->key; + const UHashTok otherValueTok = elem->value; + UnicodeString* otherKey = (UnicodeString*)otherKeyTok.pointer; + UnicodeString* otherArray = (UnicodeString*)otherValueTok.pointer; + UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH); + if(array==NULL){ + return NULL; + } + UnicodeString key(*otherKey); + for(int32_t i=0; i<UTZ_MAX_DISPLAY_STRINGS_LENGTH; i++){ + array[i].setTo(otherArray[i]); + } + hash->put(key, array, status); + if(U_FAILURE(status)){ + delete[] array; + return NULL; + } + } + return hash; +} + + +UnicodeString& +DateFormatSymbols::getZoneID(const UnicodeString& zid, UnicodeString& result, UErrorCode& status){ + if(fZoneStringsHash == NULL){ + initZoneStrings(status); + } + if(U_FAILURE(status)){ + return result; + } + UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(zid); + if (strings != NULL) { + return result.setTo(zid,0); + } + + // Do a search through the equivalency group for the given ID + int32_t n = TimeZone::countEquivalentIDs(zid); + if (n > 1) { + int32_t i; + for (i=0; i<n; ++i) { + UnicodeString equivID = TimeZone::getEquivalentID(zid, i); + if (equivID != zid) { + strings = (UnicodeString*)fZoneStringsHash->get(equivID); + if (strings != NULL) { + return result.setTo(equivID,0); + } + } + } + }else{ + result.setTo(zid); + } + return result; +} + +void +DateFormatSymbols::getZoneType(const UnicodeString& zid, const UnicodeString& text, int32_t start, + TimeZoneTranslationType& type, UnicodeString& value, UErrorCode& status){ + if(fZoneStringsHash == NULL){ + initZoneStrings(status); + } + if(U_FAILURE(status)){ + return; + } + type = TIMEZONE_COUNT; + UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(zid); + if(strings != NULL){ + for(int32_t j=0; j<UTZ_MAX_DISPLAY_STRINGS_LENGTH; j++){ + if(strings[j].length() >0 && text.caseCompare(start, strings[j].length(), strings[j], 0)==0){ + type = (TimeZoneTranslationType)j; + value.setTo(strings[j]); + return; + } + } + } +} +void +DateFormatSymbols::findZoneIDTypeValue( UnicodeString& zid, const UnicodeString& text, int32_t start, + TimeZoneTranslationType& type, UnicodeString& value, + UErrorCode& status){ + if(fZoneStringsHash == NULL){ + initZoneStrings(status); + } + if(U_FAILURE(status)){ + return; + } + const UnicodeString* myKey = NULL; + int32_t pos = 0; + TimeZoneKeysEnumeration *keys = (TimeZoneKeysEnumeration*)fZoneIDEnumeration; + while( (myKey=keys->snext(pos, status))!= NULL){ + UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(*myKey); + if(strings != NULL){ + for(int32_t j=0; j<UTZ_MAX_DISPLAY_STRINGS_LENGTH; j++){ + if(strings[j].length()>0 && text.caseCompare(start, strings[j].length(), strings[j], 0)==0){ + type = (TimeZoneTranslationType)j; + value.setTo(strings[j]); + zid.setTo(*myKey); + return; + } + } + } + } +} U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */ |