From db7d00f2cb8572cc91283d71657250b7b77ffd3d Mon Sep 17 00:00:00 2001 From: George Rhoten Date: Tue, 31 Aug 2004 18:04:12 +0000 Subject: [PATCH] ICU-4084 Improve DateFormat construction performance. X-SVN-Rev: 16223 --- icu4c/source/i18n/dtfmtsym.cpp | 63 ++++++++-------- icu4c/source/i18n/gregoimp.cpp | 78 +++++++++----------- icu4c/source/i18n/gregoimp.h | 105 ++++++++++----------------- icu4c/source/i18n/smpdtfmt.cpp | 3 +- icu4c/source/i18n/unicode/dtfmtsym.h | 4 +- 5 files changed, 113 insertions(+), 140 deletions(-) diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp index 7c2117c92e9..79a8b69bfcb 100644 --- a/icu4c/source/i18n/dtfmtsym.cpp +++ b/icu4c/source/i18n/dtfmtsym.cpp @@ -23,7 +23,6 @@ #if !UCONFIG_NO_FORMATTING #include "unicode/dtfmtsym.h" -#include "unicode/resbund.h" #include "unicode/smpdtfmt.h" #include "ucln_in.h" #include "mutex.h" @@ -40,7 +39,7 @@ * resource data. */ -#define PATTERN_CHARS_LEN 20 +#define PATTERN_CHARS_LEN 24 /** * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All @@ -48,9 +47,9 @@ */ static const UChar gPatternChars[] = { // GyMdkHmsSEDFwWahKzYeugAZ - 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45, 0x44, - 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65, 0x75, 0x67, - 0x41, 0x5A, 0 + 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45, + 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65, + 0x75, 0x67, 0x41, 0x5A, 0 }; //------------------------------------------------------ @@ -511,14 +510,16 @@ DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChar //------------------------------------------------------ void -DateFormatSymbols::initField(UnicodeString **field, int32_t& length, const ResourceBundle &data, UErrorCode &status) { +DateFormatSymbols::initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) { if (U_SUCCESS(status)) { - length = data.getSize(); + int32_t strLen = 0; + length = ures_getSize(data); *field = newUnicodeStringArray(length); if (*field) { for(int32_t i = 0; ifastCopyFrom(data.getStringEx(i, status)); + const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status); + // setTo() - see assignArray comments + (*(field)+i)->setTo(TRUE, resStr, strLen); } } else { @@ -583,9 +584,10 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError UResourceBundle *nonCalendarData = ures_open((char*)0, locale.getName(), &status); // load the first data item - ResourceBundle eras(calData.getBundleByKey(gErasTag, status).getWithFallback(gAbbreviatedTag, status)); - ResourceBundle lsweekdaysData(calData.getBundleByKey2(gDayNamesTag, gNamesAbbrTag, status)); - ResourceBundle weekdaysData(calData.getBundleByKey2(gDayNamesTag, gNamesWideTag, status)); + UResourceBundle *erasMain = calData.getByKey(gErasTag, status); + UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gAbbreviatedTag, NULL, &status); + UResourceBundle *lsweekdaysData = NULL; // Data closed by calData + UResourceBundle *weekdaysData = 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); @@ -622,16 +624,21 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError // if we make it to here, the resource data is cool, and we can get everything out // of it that we need except for the time-zone and localized-pattern data, which // are stored in a separate file - locBased.setLocaleIDs(eras.getLocale(ULOC_VALID_LOCALE, status).getName(), - eras.getLocale(ULOC_ACTUAL_LOCALE, status).getName()); + locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status), + ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status)); initField(&fEras, fErasCount, eras, status); - initField(&fMonths, fMonthsCount, calData.getBundleByKey2(gMonthNamesTag, gNamesWideTag, status), status); - initField(&fShortMonths, fShortMonthsCount, calData.getBundleByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); - initField(&fAmPms, fAmPmsCount, calData.getBundleByKey(gAmPmMarkersTag, status), status); + initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status); + initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); + initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status); // fastCopyFrom()/setTo() - see assignArray comments resStr = ures_getStringByKey(nonCalendarData, 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. + if (len < PATTERN_CHARS_LEN) { + 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); @@ -658,7 +665,8 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError } // {sfb} fixed to handle 1-based weekdays - fWeekdaysCount = weekdaysData.getSize(); + weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status); + fWeekdaysCount = ures_getSize(weekdaysData); fWeekdays = new UnicodeString[fWeekdaysCount+1]; /* test for NULL */ if (fWeekdays == 0) { @@ -667,12 +675,14 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError } // leave fWeekdays[0] empty for(i = 0; i %s - from MAIN %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status)); + fprintf(stderr, "%p: get %s -> %s - from MAIN %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status)); #endif - } - if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) { - status = U_ZERO_ERROR; // retry with fallback (gregorian) - fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status); + } + if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) { + status = U_ZERO_ERROR; // retry with fallback (gregorian) + fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status); #if defined (U_DEBUG_CALDATA) - fprintf(stderr, "%p: get %s -> %s - from FALLBACK %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status)); + fprintf(stderr, "%p: get %s -> %s - from FALLBACK %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status)); #endif - } - return fFillin; -} - -ResourceBundle CalendarData::getBundleByKey(const char *key, UErrorCode &status) { - return ResourceBundle(getByKey(key,status), status); + } + return fFillin; } UResourceBundle* CalendarData::getByKey2(const char *key, const char *subKey, UErrorCode& status) { - if(U_FAILURE(status)) { - return NULL; - } + if(U_FAILURE(status)) { + return NULL; + } - if(fBundle) { + if(fBundle) { #if defined (U_DEBUG_CALDATA) - fprintf(stderr, "%p: //\n"); + fprintf(stderr, "%p: //\n"); #endif - fFillin = ures_getByKeyWithFallback(fBundle, key, fFillin, &status); - fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status); - fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status); + fFillin = ures_getByKeyWithFallback(fBundle, key, fFillin, &status); + fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status); + fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status); #if defined (U_DEBUG_CALDATA) - fprintf(stderr, "%p: get %s/format/%s -> %s - from MAIN %s\n", this, key, subKey, u_errorName(status), ures_getLocale(fFillin, &status)); + fprintf(stderr, "%p: get %s/format/%s -> %s - from MAIN %s\n", this, key, subKey, u_errorName(status), ures_getLocale(fFillin, &status)); #endif - } - if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) { - status = U_ZERO_ERROR; // retry with fallback (gregorian) - fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status); - fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status); - fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status); + } + if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) { + status = U_ZERO_ERROR; // retry with fallback (gregorian) + fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status); + fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status); + fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status); #if defined (U_DEBUG_CALDATA) - fprintf(stderr, "%p: get %s/format/%s -> %s - from FALLBACK %s\n",this, key, subKey, u_errorName(status), ures_getLocale(fFillin,&status)); + fprintf(stderr, "%p: get %s/format/%s -> %s - from FALLBACK %s\n",this, key, subKey, u_errorName(status), ures_getLocale(fFillin,&status)); #endif - } + } //// handling of 'default' keyword on failure: Commented out for 3.0. // if((status == U_MISSING_RESOURCE_ERROR) && @@ -265,11 +261,7 @@ UResourceBundle* CalendarData::getByKey2(const char *key, const char *subKey, UE // } // } - return fFillin; -} - -ResourceBundle CalendarData::getBundleByKey2(const char *key, const char *subKey, UErrorCode& status) { - return ResourceBundle(getByKey2(key, subKey, status), status); + return fFillin; } UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CalendarData); diff --git a/icu4c/source/i18n/gregoimp.h b/icu4c/source/i18n/gregoimp.h index fdbfa78e711..f24a35dbc62 100644 --- a/icu4c/source/i18n/gregoimp.h +++ b/icu4c/source/i18n/gregoimp.h @@ -262,66 +262,41 @@ inline int32_t Grego::gregorianShift(int32_t eyear) { * @internal ICU 3.0 */ class U_I18N_API CalendarData : public UObject { - public: - /** - * Construct a CalendarData from the given locale. - * @param loc locale to use - the 'calendar' keyword will be used, respecting the - * 'default' value in the resource bundle. - * @param status error code - */ - //CalendarData(const Locale& loc, UErrorCode& status); +public: + /** + * Construct a CalendarData from the given locale. + * @param loc locale to use. The 'calendar' keyword will be ignored. + * @param type calendar type. NULL indicates the gregorian calendar. + * No default lookup is done. + * @param status error code + */ + CalendarData(const Locale& loc, const char *type, UErrorCode& status); - /** - * Construct a CalendarData from the given locale. - * @param loc locale to use. The 'calendar' keyword will be ignored. - * @param type calendar type. NULL indicates the gregorian calendar. - * No default lookup is done. - * @param status error code - */ - CalendarData(const Locale& loc, const char *type, UErrorCode& status); - - /** - * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()! - * - * @param key Resource key to data - * @param status Error Status - * @internal - */ - UResourceBundle* getByKey(const char *key, UErrorCode& status); + /** + * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()! + * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API. + * + * @param key Resource key to data + * @param status Error Status + * @internal + */ + UResourceBundle* getByKey(const char *key, UErrorCode& status); - /** - * Load data for calendar. returns a ResourceBundle object - * - * @param key Resource key to data - * @param status Error Status - * @internal - */ - ResourceBundle getBundleByKey(const char *key, UErrorCode& status); + /** + * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()! + * There is an implicit key of 'format' + * data is located in: "calendar/key/format/subKey" + * for example, calendar/dayNames/format/abbreviated + * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API. + * + * @param key Resource key to data + * @param subKey Resource key to data + * @param status Error Status + * @internal + */ + UResourceBundle* getByKey2(const char *key, const char *subKey, UErrorCode& status); - /** - * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()! - * There is an implicit key of 'format' - * data is located in: "calendar/key/format/subKey" - * for example, calendar/dayNames/format/abbreviated - * - * @param key Resource key to data - * @param subKey Resource key to data - * @param status Error Status - * @internal - */ - UResourceBundle* getByKey2(const char *key, const char *subKey, UErrorCode& status); - - /** - * Load data for calendar. Returns a ResourceBundle object - * - * @param key Resource key to data - * @param subKey Resource key to data - * @param status Error Status - * @internal - */ - ResourceBundle getBundleByKey2(const char *key, const char *subKey, UErrorCode& status); - - ~CalendarData(); + ~CalendarData(); /** * Override Calendar Returns a unique class ID POLYMORPHICALLY. Pure virtual @@ -348,14 +323,14 @@ class U_I18N_API CalendarData : public UObject { */ static UClassID U_EXPORT2 getStaticClassID(void); - private: - void initData(const char *locale, const char *type, UErrorCode& status); - - UResourceBundle *fFillin; - UResourceBundle *fOtherFillin; - UResourceBundle *fBundle; - UResourceBundle *fFallback; - CalendarData(); // Not implemented. +private: + void initData(const char *locale, const char *type, UErrorCode& status); + + UResourceBundle *fFillin; + UResourceBundle *fOtherFillin; + UResourceBundle *fBundle; + UResourceBundle *fFallback; + CalendarData(); // Not implemented. }; U_NAMESPACE_END diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp index 8868a83088a..97aa3e41a58 100644 --- a/icu4c/source/i18n/smpdtfmt.cpp +++ b/icu4c/source/i18n/smpdtfmt.cpp @@ -278,7 +278,8 @@ void SimpleDateFormat::construct(EStyle timeStyle, initializeCalendar(NULL, locale, status); CalendarData calData(locale, fCalendar?fCalendar->getType():NULL, status); - ResourceBundle dateTimePatterns = calData.getBundleByKey(gDateTimePatternsTag, status); + UResourceBundle *dtp = calData.getByKey(gDateTimePatternsTag, status); + ResourceBundle dateTimePatterns(dtp, status); if (U_FAILURE(status)) return; if (dateTimePatterns.getSize() <= kDateTime) diff --git a/icu4c/source/i18n/unicode/dtfmtsym.h b/icu4c/source/i18n/unicode/dtfmtsym.h index 3546ab093d9..dfe3b868c35 100644 --- a/icu4c/source/i18n/unicode/dtfmtsym.h +++ b/icu4c/source/i18n/unicode/dtfmtsym.h @@ -24,7 +24,7 @@ #include "unicode/uobject.h" #include "unicode/locid.h" -#include "unicode/resbund.h" +#include "unicode/ures.h" U_NAMESPACE_BEGIN @@ -412,7 +412,7 @@ private: DateFormatSymbols(); // default constructor not implemented - void initField(UnicodeString **field, int32_t& length, const ResourceBundle &data, UErrorCode &status); + void initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status); void initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status); /**