ICU-11912 Adding more efficient implementation of getDisplayNames(), which was already present in Java

X-SVN-Rev: 39041
This commit is contained in:
Shane Carr 2016-08-11 23:29:51 +00:00
parent e271d8a317
commit d88a4109a5
5 changed files with 106 additions and 44 deletions

View file

@ -1323,7 +1323,7 @@ DateFormatSymbols::initZoneStringsArray(void) {
}
zarray[i][0].setTo(*tzid);
tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1);
tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
i++;
}
@ -1337,6 +1337,7 @@ DateFormatSymbols::initZoneStringsArray(void) {
}
}
uprv_free(zarray);
zarray = NULL;
}
}

View file

@ -119,6 +119,7 @@ public:
UnicodeString& getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const;
void loadAllDisplayNames(UErrorCode& status);
void getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[], UErrorCode& status) const;
MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
private:
@ -287,6 +288,11 @@ TimeZoneNamesDelegate::loadAllDisplayNames(UErrorCode& status) {
fTZnamesCacheEntry->names->loadAllDisplayNames(status);
}
void
TimeZoneNamesDelegate::getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[], UErrorCode& status) const {
fTZnamesCacheEntry->names->getDisplayNames(tzID, types, numTypes, date, dest, status);
}
TimeZoneNames::MatchInfoCollection*
TimeZoneNamesDelegate::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
return fTZnamesCacheEntry->names->find(text, start, types, status);
@ -339,26 +345,26 @@ TimeZoneNames::getDisplayName(const UnicodeString& tzID, UTimeZoneNameType type,
return name;
}
// Empty default implementation, to be overriden in tznames_impl.cpp.
void
TimeZoneNames::loadAllDisplayNames(UErrorCode& status) {
return loadAllDisplayNames(status);
TimeZoneNames::loadAllDisplayNames(UErrorCode& /*status*/) {
}
// A default, lightweight implementation of getDisplayNames.
// Overridden in tznames_impl.cpp.
void
TimeZoneNames::getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[]) const {
TimeZoneNames::getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[], UErrorCode& status) const {
if (U_FAILURE(status)) { return; }
if (tzID.isEmpty()) { return; }
UnicodeString mzID;
for (int i = 0; i < numTypes; i++) {
UnicodeString name;
UTimeZoneNameType type = types[i];
getTimeZoneDisplayName(tzID, type, name);
if (name.isEmpty()) {
getTimeZoneDisplayName(tzID, types[i], dest[i]);
if (dest[i].isEmpty()) {
if (mzID.isEmpty()) {
getMetaZoneID(tzID, date, mzID);
}
getMetaZoneDisplayName(mzID, type, name);
getMetaZoneDisplayName(mzID, types[i], dest[i]);
}
dest[i].setTo(name);
}
}

View file

@ -1050,7 +1050,7 @@ TimeZoneNamesImpl::initialize(const Locale& locale, UErrorCode& status) {
TimeZone *tz = TimeZone::createDefault();
const UChar *tzID = ZoneMeta::getCanonicalCLDRID(*tz);
if (tzID != NULL) {
loadStrings(UnicodeString(tzID));
loadStrings(UnicodeString(tzID), status);
}
delete tz;
@ -1062,20 +1062,15 @@ TimeZoneNamesImpl::initialize(const Locale& locale, UErrorCode& status) {
* except initializer.
*/
void
TimeZoneNamesImpl::loadStrings(const UnicodeString& tzCanonicalID) {
loadTimeZoneNames(tzCanonicalID);
TimeZoneNamesImpl::loadStrings(const UnicodeString& tzCanonicalID, UErrorCode& status) {
loadTimeZoneNames(tzCanonicalID, status);
LocalPointer<StringEnumeration> mzIDs(getAvailableMetaZoneIDs(tzCanonicalID, status));
if (U_FAILURE(status)) { return; }
U_ASSERT(!mzIDs.isNull());
UErrorCode status = U_ZERO_ERROR;
StringEnumeration *mzIDs = getAvailableMetaZoneIDs(tzCanonicalID, status);
if (U_SUCCESS(status) && mzIDs != NULL) {
const UnicodeString *mzID;
while ((mzID = mzIDs->snext(status))) {
if (U_FAILURE(status)) {
break;
}
loadMetaZoneNames(*mzID);
}
delete mzIDs;
const UnicodeString *mzID;
while ((mzID = mzIDs->snext(status)) && U_SUCCESS(status)) {
loadMetaZoneNames(*mzID, status);
}
}
@ -1196,7 +1191,6 @@ TimeZoneNamesImpl::_getReferenceZoneID(const UnicodeString& mzID, const char* re
return tzID;
}
UnicodeString&
TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
UTimeZoneNameType type,
@ -1211,7 +1205,9 @@ TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
{
Mutex lock(&gDataMutex);
znames = nonConstThis->loadMetaZoneNames(mzID);
UErrorCode status = U_ZERO_ERROR;
znames = nonConstThis->loadMetaZoneNames(mzID, status);
if (U_FAILURE(status)) { return name; }
}
if (znames != NULL) {
@ -1235,7 +1231,9 @@ TimeZoneNamesImpl::getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNa
{
Mutex lock(&gDataMutex);
tznames = nonConstThis->loadTimeZoneNames(tzID);
UErrorCode status = U_ZERO_ERROR;
tznames = nonConstThis->loadTimeZoneNames(tzID, status);
if (U_FAILURE(status)) { return name; }
}
if (tznames != NULL) {
@ -1256,7 +1254,9 @@ TimeZoneNamesImpl::getExemplarLocationName(const UnicodeString& tzID, UnicodeStr
{
Mutex lock(&gDataMutex);
tznames = nonConstThis->loadTimeZoneNames(tzID);
UErrorCode status = U_ZERO_ERROR;
tznames = nonConstThis->loadTimeZoneNames(tzID, status);
if (U_FAILURE(status)) { return name; }
}
if (tznames != NULL) {
@ -1290,14 +1290,13 @@ static void mergeTimeZoneKey(const UnicodeString& mzID, char* result) {
* This method updates the cache and must be called with a lock
*/
ZNames*
TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID) {
TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID, UErrorCode& status) {
if (U_FAILURE(status)) { return NULL; }
U_ASSERT(mzID.length() <= ZID_KEY_MAX - MZ_PREFIX_LEN);
UErrorCode status = U_ZERO_ERROR;
UChar mzIDKey[ZID_KEY_MAX + 1];
mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
U_ASSERT(status == U_ZERO_ERROR); // already checked length above
U_ASSERT(U_SUCCESS(status)); // already checked length above
mzIDKey[mzID.length()] = 0;
void* mznames = uhash_get(fMZNamesMap, mzIDKey);
@ -1319,14 +1318,13 @@ TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID) {
* This method updates the cache and must be called with a lock
*/
ZNames*
TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID) {
TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID, UErrorCode& status) {
if (U_FAILURE(status)) { return NULL; }
U_ASSERT(tzID.length() <= ZID_KEY_MAX);
UErrorCode status = U_ZERO_ERROR;
UChar tzIDKey[ZID_KEY_MAX + 1];
int32_t tzIDKeyLen = tzID.extract(tzIDKey, ZID_KEY_MAX + 1, status);
U_ASSERT(status == U_ZERO_ERROR); // already checked length above
U_ASSERT(U_SUCCESS(status)); // already checked length above
tzIDKey[tzIDKeyLen] = 0;
void *tznames = uhash_get(fTZNamesMap, tzIDKey);
@ -1582,6 +1580,61 @@ void TimeZoneNamesImpl::loadAllDisplayNames(UErrorCode& status) {
}
}
void TimeZoneNamesImpl::getDisplayNames(const UnicodeString& tzID,
const UTimeZoneNameType types[], int32_t numTypes,
UDate date, UnicodeString dest[], UErrorCode& status) const {
if (U_FAILURE(status)) return;
if (tzID.isEmpty()) { return; }
void* tznames = NULL;
void* mznames = NULL;
TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl*>(this);
// Load the time zone strings
{
Mutex lock(&gDataMutex);
tznames = (void*) nonConstThis->loadTimeZoneNames(tzID, status);
if (U_FAILURE(status)) { return; }
}
U_ASSERT(tznames != NULL);
// Load the values into the dest array
for (int i = 0; i < numTypes; i++) {
UTimeZoneNameType type = types[i];
const UChar* name = ((ZNames*)tznames)->getName(type);
if (name == NULL) {
if (mznames == NULL) {
// Load the meta zone name
UnicodeString mzID;
getMetaZoneID(tzID, date, mzID);
if (mzID.isEmpty()) {
mznames = (void*) EMPTY;
} else {
// Load the meta zone strings
// Mutex is scoped to the "else" statement
Mutex lock(&gDataMutex);
mznames = (void*) nonConstThis->loadMetaZoneNames(mzID, status);
if (U_FAILURE(status)) { return; }
// Note: when the metazone doesn't exist, in Java, loadMetaZoneNames returns
// a dummy object instead of NULL.
if (mznames == NULL) {
mznames = (void*) EMPTY;
}
}
}
U_ASSERT(mznames != NULL);
if (mznames != EMPTY) {
name = ((ZNames*)mznames)->getName(type);
}
}
if (name != NULL) {
dest[i].setTo(TRUE, name, -1);
} else {
dest[i].setToBogus();
}
}
}
// Caller must synchronize.
void TimeZoneNamesImpl::internalLoadAllDisplayNames(UErrorCode& status) {
if (!fNamesFullyLoaded) {
@ -1604,8 +1657,8 @@ void TimeZoneNamesImpl::internalLoadAllDisplayNames(UErrorCode& status) {
UnicodeString copy(*id);
void* value = uhash_get(fTZNamesMap, copy.getTerminatedBuffer());
if (value == NULL) {
// loadStrings also load related metazone strings
loadStrings(*id);
// loadStrings also loads related metazone strings
loadStrings(*id, status);
}
}
}

View file

@ -186,8 +186,8 @@ public:
TimeZoneNames::MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
void loadAllDisplayNames(UErrorCode& errorCode);
void internalLoadAllDisplayNames(UErrorCode& errorCode);
void loadAllDisplayNames(UErrorCode& status);
void getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[], UErrorCode& status) const;
static UnicodeString& getDefaultExemplarLocationName(const UnicodeString& tzID, UnicodeString& name);
@ -212,14 +212,16 @@ private:
void initialize(const Locale& locale, UErrorCode& status);
void cleanup();
void loadStrings(const UnicodeString& tzCanonicalID);
void loadStrings(const UnicodeString& tzCanonicalID, UErrorCode& status);
ZNames* loadMetaZoneNames(const UnicodeString& mzId);
ZNames* loadTimeZoneNames(const UnicodeString& mzId);
ZNames* loadMetaZoneNames(const UnicodeString& mzId, UErrorCode& status);
ZNames* loadTimeZoneNames(const UnicodeString& mzId, UErrorCode& status);
TimeZoneNames::MatchInfoCollection* doFind(ZNameSearchHandler& handler,
const UnicodeString& text, int32_t start, UErrorCode& status) const;
void addAllNamesIntoTrie(UErrorCode& errorCode);
void internalLoadAllDisplayNames(UErrorCode& status);
struct ZoneStringsLoader;
};

View file

@ -300,7 +300,7 @@ public:
* @internal For specific users only until proposed publicly.
* @deprecated This API is ICU internal only.
*/
virtual void getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[]) const;
virtual void getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[], UErrorCode& status) const;
/**
* <code>MatchInfoCollection</code> represents a collection of time zone name matches used by