ICU-13602 Check error status for lazily instantiated TiemZoneFormat in SimpleDateFormat.

X-SVN-Rev: 41413
This commit is contained in:
Yoshito Umaoka 2018-05-19 00:18:25 +00:00
parent 2627d76fbe
commit 9cc7d14b62
2 changed files with 84 additions and 56 deletions

View File

@ -1695,100 +1695,101 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
UnicodeString zoneString(zsbuf, 0, UPRV_LENGTHOF(zsbuf)); UnicodeString zoneString(zsbuf, 0, UPRV_LENGTHOF(zsbuf));
const TimeZone& tz = cal.getTimeZone(); const TimeZone& tz = cal.getTimeZone();
UDate date = cal.getTime(status); UDate date = cal.getTime(status);
const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) { if (U_SUCCESS(status)) {
if (patternCharIndex == UDAT_TIMEZONE_FIELD) { if (patternCharIndex == UDAT_TIMEZONE_FIELD) {
if (count < 4) { if (count < 4) {
// "z", "zz", "zzz" // "z", "zz", "zzz"
tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort; capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort;
} else { } else {
// "zzzz" or longer // "zzzz" or longer
tzFormat()->format(UTZFMT_STYLE_SPECIFIC_LONG, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_SPECIFIC_LONG, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong; capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong;
} }
} }
else if (patternCharIndex == UDAT_TIMEZONE_RFC_FIELD) { else if (patternCharIndex == UDAT_TIMEZONE_RFC_FIELD) {
if (count < 4) { if (count < 4) {
// "Z" // "Z"
tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString);
} else if (count == 5) { } else if (count == 5) {
// "ZZZZZ" // "ZZZZZ"
tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString);
} else { } else {
// "ZZ", "ZZZ", "ZZZZ" // "ZZ", "ZZZ", "ZZZZ"
tzFormat()->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString);
} }
} }
else if (patternCharIndex == UDAT_TIMEZONE_GENERIC_FIELD) { else if (patternCharIndex == UDAT_TIMEZONE_GENERIC_FIELD) {
if (count == 1) { if (count == 1) {
// "v" // "v"
tzFormat()->format(UTZFMT_STYLE_GENERIC_SHORT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_GENERIC_SHORT, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort; capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort;
} else if (count == 4) { } else if (count == 4) {
// "vvvv" // "vvvv"
tzFormat()->format(UTZFMT_STYLE_GENERIC_LONG, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_GENERIC_LONG, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong; capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong;
} }
} }
else if (patternCharIndex == UDAT_TIMEZONE_SPECIAL_FIELD) { else if (patternCharIndex == UDAT_TIMEZONE_SPECIAL_FIELD) {
if (count == 1) { if (count == 1) {
// "V" // "V"
tzFormat()->format(UTZFMT_STYLE_ZONE_ID_SHORT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ZONE_ID_SHORT, tz, date, zoneString);
} else if (count == 2) { } else if (count == 2) {
// "VV" // "VV"
tzFormat()->format(UTZFMT_STYLE_ZONE_ID, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ZONE_ID, tz, date, zoneString);
} else if (count == 3) { } else if (count == 3) {
// "VVV" // "VVV"
tzFormat()->format(UTZFMT_STYLE_EXEMPLAR_LOCATION, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_EXEMPLAR_LOCATION, tz, date, zoneString);
} else if (count == 4) { } else if (count == 4) {
// "VVVV" // "VVVV"
tzFormat()->format(UTZFMT_STYLE_GENERIC_LOCATION, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_GENERIC_LOCATION, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageZoneLong; capContextUsageType = DateFormatSymbols::kCapContextUsageZoneLong;
} }
} }
else if (patternCharIndex == UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD) { else if (patternCharIndex == UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD) {
if (count == 1) { if (count == 1) {
// "O" // "O"
tzFormat()->format(UTZFMT_STYLE_LOCALIZED_GMT_SHORT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_LOCALIZED_GMT_SHORT, tz, date, zoneString);
} else if (count == 4) { } else if (count == 4) {
// "OOOO" // "OOOO"
tzFormat()->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString);
} }
} }
else if (patternCharIndex == UDAT_TIMEZONE_ISO_FIELD) { else if (patternCharIndex == UDAT_TIMEZONE_ISO_FIELD) {
if (count == 1) { if (count == 1) {
// "X" // "X"
tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_SHORT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_BASIC_SHORT, tz, date, zoneString);
} else if (count == 2) { } else if (count == 2) {
// "XX" // "XX"
tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_FIXED, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_BASIC_FIXED, tz, date, zoneString);
} else if (count == 3) { } else if (count == 3) {
// "XXX" // "XXX"
tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_FIXED, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_FIXED, tz, date, zoneString);
} else if (count == 4) { } else if (count == 4) {
// "XXXX" // "XXXX"
tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_FULL, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_BASIC_FULL, tz, date, zoneString);
} else if (count == 5) { } else if (count == 5) {
// "XXXXX" // "XXXXX"
tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString);
} }
} }
else if (patternCharIndex == UDAT_TIMEZONE_ISO_LOCAL_FIELD) { else if (patternCharIndex == UDAT_TIMEZONE_ISO_LOCAL_FIELD) {
if (count == 1) { if (count == 1) {
// "x" // "x"
tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_SHORT, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_SHORT, tz, date, zoneString);
} else if (count == 2) { } else if (count == 2) {
// "xx" // "xx"
tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FIXED, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FIXED, tz, date, zoneString);
} else if (count == 3) { } else if (count == 3) {
// "xxx" // "xxx"
tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FIXED, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FIXED, tz, date, zoneString);
} else if (count == 4) { } else if (count == 4) {
// "xxxx" // "xxxx"
tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString);
} else if (count == 5) { } else if (count == 5) {
// "xxxxx" // "xxxxx"
tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL, tz, date, zoneString); tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL, tz, date, zoneString);
} }
} }
else { else {
@ -3393,32 +3394,42 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
case UDAT_TIMEZONE_FIELD: // 'z' case UDAT_TIMEZONE_FIELD: // 'z'
{ {
UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_SPECIFIC_SHORT : UTZFMT_STYLE_SPECIFIC_LONG; UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_SPECIFIC_SHORT : UTZFMT_STYLE_SPECIFIC_LONG;
TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) {
TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType);
if (tz != NULL) { if (tz != NULL) {
cal.adoptTimeZone(tz); cal.adoptTimeZone(tz);
return pos.getIndex(); return pos.getIndex();
} }
}
return -start;
} }
break; break;
case UDAT_TIMEZONE_RFC_FIELD: // 'Z' case UDAT_TIMEZONE_RFC_FIELD: // 'Z'
{ {
UTimeZoneFormatStyle style = (count < 4) ? UTimeZoneFormatStyle style = (count < 4) ?
UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL : ((count == 5) ? UTZFMT_STYLE_ISO_EXTENDED_FULL: UTZFMT_STYLE_LOCALIZED_GMT); UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL : ((count == 5) ? UTZFMT_STYLE_ISO_EXTENDED_FULL: UTZFMT_STYLE_LOCALIZED_GMT);
TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) {
TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType);
if (tz != NULL) { if (tz != NULL) {
cal.adoptTimeZone(tz); cal.adoptTimeZone(tz);
return pos.getIndex(); return pos.getIndex();
} }
}
return -start; return -start;
} }
case UDAT_TIMEZONE_GENERIC_FIELD: // 'v' case UDAT_TIMEZONE_GENERIC_FIELD: // 'v'
{ {
UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_GENERIC_SHORT : UTZFMT_STYLE_GENERIC_LONG; UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_GENERIC_SHORT : UTZFMT_STYLE_GENERIC_LONG;
TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) {
TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType);
if (tz != NULL) { if (tz != NULL) {
cal.adoptTimeZone(tz); cal.adoptTimeZone(tz);
return pos.getIndex(); return pos.getIndex();
} }
}
return -start; return -start;
} }
case UDAT_TIMEZONE_SPECIAL_FIELD: // 'V' case UDAT_TIMEZONE_SPECIAL_FIELD: // 'V'
@ -3438,21 +3449,27 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
style = UTZFMT_STYLE_GENERIC_LOCATION; style = UTZFMT_STYLE_GENERIC_LOCATION;
break; break;
} }
TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) {
TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType);
if (tz != NULL) { if (tz != NULL) {
cal.adoptTimeZone(tz); cal.adoptTimeZone(tz);
return pos.getIndex(); return pos.getIndex();
} }
}
return -start; return -start;
} }
case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD: // 'O' case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD: // 'O'
{ {
UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_LOCALIZED_GMT_SHORT : UTZFMT_STYLE_LOCALIZED_GMT; UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_LOCALIZED_GMT_SHORT : UTZFMT_STYLE_LOCALIZED_GMT;
TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) {
TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType);
if (tz != NULL) { if (tz != NULL) {
cal.adoptTimeZone(tz); cal.adoptTimeZone(tz);
return pos.getIndex(); return pos.getIndex();
} }
}
return -start; return -start;
} }
case UDAT_TIMEZONE_ISO_FIELD: // 'X' case UDAT_TIMEZONE_ISO_FIELD: // 'X'
@ -3475,11 +3492,14 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
style = UTZFMT_STYLE_ISO_EXTENDED_FULL; style = UTZFMT_STYLE_ISO_EXTENDED_FULL;
break; break;
} }
TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) {
TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType);
if (tz != NULL) { if (tz != NULL) {
cal.adoptTimeZone(tz); cal.adoptTimeZone(tz);
return pos.getIndex(); return pos.getIndex();
} }
}
return -start; return -start;
} }
case UDAT_TIMEZONE_ISO_LOCAL_FIELD: // 'x' case UDAT_TIMEZONE_ISO_LOCAL_FIELD: // 'x'
@ -3502,11 +3522,14 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
style = UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL; style = UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL;
break; break;
} }
TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); const TimeZoneFormat *tzfmt = tzFormat(status);
if (U_SUCCESS(status)) {
TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType);
if (tz != NULL) { if (tz != NULL) {
cal.adoptTimeZone(tz); cal.adoptTimeZone(tz);
return pos.getIndex(); return pos.getIndex();
} }
}
return -start; return -start;
} }
// currently no pattern character is defined for UDAT_TIME_SEPARATOR_FIELD // currently no pattern character is defined for UDAT_TIME_SEPARATOR_FIELD
@ -3856,7 +3879,13 @@ SimpleDateFormat::setDateFormatSymbols(const DateFormatSymbols& newFormatSymbols
//---------------------------------------------------------------------- //----------------------------------------------------------------------
const TimeZoneFormat* const TimeZoneFormat*
SimpleDateFormat::getTimeZoneFormat(void) const { SimpleDateFormat::getTimeZoneFormat(void) const {
return (const TimeZoneFormat*)tzFormat(); // TimeZoneFormat initialization might fail when out of memory.
// If we always initialize TimeZoneFormat instance, we can return
// such status there. For now, this implementation lazily instantiates
// a TimeZoneFormat for performance optimization reasons, but cannot
// propagate such error (probably just out of memory case) to the caller.
UErrorCode status = U_ZERO_ERROR;
return (const TimeZoneFormat*)tzFormat(status);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -4123,12 +4152,11 @@ SimpleDateFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) const
// Lazy TimeZoneFormat instantiation, semantically const. // Lazy TimeZoneFormat instantiation, semantically const.
TimeZoneFormat * TimeZoneFormat *
SimpleDateFormat::tzFormat() const { SimpleDateFormat::tzFormat(UErrorCode &status) const {
if (fTimeZoneFormat == NULL) { if (fTimeZoneFormat == NULL) {
umtx_lock(&LOCK); umtx_lock(&LOCK);
{ {
if (fTimeZoneFormat == NULL) { if (fTimeZoneFormat == NULL) {
UErrorCode status = U_ZERO_ERROR;
TimeZoneFormat *tzfmt = TimeZoneFormat::createInstance(fLocale, status); TimeZoneFormat *tzfmt = TimeZoneFormat::createInstance(fLocale, status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return NULL; return NULL;

View File

@ -1518,7 +1518,7 @@ private:
/** /**
* Lazy TimeZoneFormat instantiation, semantically const * Lazy TimeZoneFormat instantiation, semantically const
*/ */
TimeZoneFormat *tzFormat() const; TimeZoneFormat *tzFormat(UErrorCode &status) const;
const NumberFormat* getNumberFormatByIndex(UDateFormatField index) const; const NumberFormat* getNumberFormatByIndex(UDateFormatField index) const;