Skip to content

Commit

Permalink
ICU-22994 Use C++ typeid() instead of Calendar::getType() for calenda…
Browse files Browse the repository at this point in the history
…r type comparison

See #3310
  • Loading branch information
FrankYFTang authored and roubert committed Jan 31, 2025
1 parent cb43440 commit ede201c
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 18 deletions.
7 changes: 3 additions & 4 deletions icu4c/source/i18n/datefmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
#include <stdio.h>
#endif
#include <typeinfo>

// *****************************************************************************
// class DateFormat
Expand Down Expand Up @@ -279,9 +280,8 @@ UnicodeString&
DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
if (fCalendar != nullptr) {
UErrorCode ec = U_ZERO_ERROR;
const auto* calType = fCalendar->getType();
// Avoid a heap allocation and corresponding free for the common case
if (uprv_strcmp(calType, "gregorian") == 0) {
if (typeid(*fCalendar) == typeid(GregorianCalendar)) {
GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar));
cal.setTime(date, ec);
if (U_SUCCESS(ec)) {
Expand Down Expand Up @@ -309,9 +309,8 @@ DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* p
UErrorCode& status) const {
if (fCalendar != nullptr) {
UErrorCode ec = U_ZERO_ERROR;
const auto* calType = fCalendar->getType();
// Avoid a heap allocation and corresponding free for the common case
if (uprv_strcmp(calType, "gregorian") == 0) {
if (typeid(*fCalendar) == typeid(GregorianCalendar)) {
GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar));
cal.setTime(date, ec);
if (U_SUCCESS(ec)) {
Expand Down
30 changes: 18 additions & 12 deletions icu4c/source/i18n/smpdtfmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
#include "dayperiodrules.h"
#include "tznames_impl.h" // ZONE_NAME_U16_MAX
#include "number_utypes.h"
#include "chnsecal.h"
#include "dangical.h"
#include "japancal.h"
#include <typeinfo>

#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
#include <stdio.h>
Expand Down Expand Up @@ -945,7 +949,8 @@ SimpleDateFormat::initialize(const Locale& locale,
// if format is non-numeric (includes 年) and fDateOverride is not already specified.
// Now this does get updated if applyPattern subsequently changes the pattern type.
if (fDateOverride.isBogus() && fHasHanYearChar &&
fCalendar != nullptr && uprv_strcmp(fCalendar->getType(),"japanese") == 0 &&
fCalendar != nullptr &&
typeid(*fCalendar) == typeid(JapaneseCalendar) &&
uprv_strcmp(fLocale.getLanguage(),"ja") == 0) {
fDateOverride.setTo(u"y=jpanyear", -1);
}
Expand Down Expand Up @@ -1050,7 +1055,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
}
Calendar* workCal = &cal;
Calendar* calClone = nullptr;
if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
if (&cal != fCalendar && typeid(cal) != typeid(*fCalendar)) {
// Different calendar type
// We use the time and time zone from the input calendar, but
// do not use the input calendar for field calculation.
Expand Down Expand Up @@ -1523,8 +1528,8 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
// "GGGG" is wide era name, "GGGGG" is narrow era name, anything else is abbreviated name
case UDAT_ERA_FIELD:
{
const auto* calType = cal.getType();
if (uprv_strcmp(calType,"chinese") == 0 || uprv_strcmp(calType,"dangi") == 0) {
if (typeid(cal) == typeid(ChineseCalendar) ||
typeid(cal) == typeid(DangiCalendar)) {
zeroPaddingNumber(currentNumberFormat,appendTo, value, 1, 9); // as in ICU4J
} else {
if (count == 5) {
Expand Down Expand Up @@ -1575,7 +1580,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
// for "MMMMM"/"LLLLL", use the narrow form
case UDAT_MONTH_FIELD:
case UDAT_STANDALONE_MONTH_FIELD:
if (uprv_strcmp(cal.getType(),"hebrew") == 0) {
if (typeid(cal) == typeid(HebrewCalendar)) {
if (HebrewCalendar::isLeapYear(cal.get(UCAL_YEAR,status)) && value == 6 && count >= 3 )
value = 13; // Show alternate form for Adar II in leap years in Hebrew calendar.
if (!HebrewCalendar::isLeapYear(cal.get(UCAL_YEAR,status)) && value >= 6 && count < 3 )
Expand Down Expand Up @@ -2272,7 +2277,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&

Calendar* calClone = nullptr;
Calendar *workCal = &cal;
if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
if (&cal != fCalendar && typeid(cal) != typeid(*fCalendar)) {
// Different calendar type
// We use the time/zone from the input calendar, but
// do not use the input calendar for field calculation.
Expand Down Expand Up @@ -2903,7 +2908,7 @@ int32_t SimpleDateFormat::matchAlphaMonthStrings(const UnicodeString& text,

if (bestMatch >= 0) {
// Adjustment for Hebrew Calendar month Adar II
if (!strcmp(cal.getType(),"hebrew") && bestMatch==13) {
if (typeid(cal) == typeid(HebrewCalendar) && bestMatch==13) {
cal.set(UCAL_MONTH,6);
} else {
cal.set(UCAL_MONTH, bestMatch);
Expand Down Expand Up @@ -2963,7 +2968,7 @@ int32_t SimpleDateFormat::matchString(const UnicodeString& text,
if (bestMatch >= 0) {
if (field < UCAL_FIELD_COUNT) {
// Adjustment for Hebrew Calendar month Adar II
if (!strcmp(cal.getType(),"hebrew") && field==UCAL_MONTH && bestMatch==13) {
if (typeid(cal) == typeid(HebrewCalendar) && field==UCAL_MONTH && bestMatch==13) {
cal.set(field,6);
} else {
if (field == UCAL_YEAR) {
Expand Down Expand Up @@ -3052,7 +3057,6 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
if (numericLeapMonthFormatter != nullptr) {
numericLeapMonthFormatter->setFormats(reinterpret_cast<const Format**>(&currentNumberFormat), 1);
}
UBool isChineseCalendar = (uprv_strcmp(cal.getType(),"chinese") == 0 || uprv_strcmp(cal.getType(),"dangi") == 0);

// If there are any spaces here, skip over them. If we hit the end
// of the string, then fail.
Expand All @@ -3068,6 +3072,8 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
}
pos.setIndex(start);

UBool isChineseCalendar = typeid(cal) == typeid(ChineseCalendar) ||
typeid(cal) == typeid(DangiCalendar);
// We handle a few special cases here where we need to parse
// a number value. We handle further, more generic cases below. We need
// to handle some of them here because some fields require extra processing on
Expand Down Expand Up @@ -3289,7 +3295,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
// When parsing month numbers from the Hebrew Calendar, we might need to adjust the month depending on whether
// or not it was a leap year. We may or may not yet know what year it is, so might have to delay checking until
// the year is parsed.
if (!strcmp(cal.getType(),"hebrew")) {
if (typeid(cal) == typeid(HebrewCalendar)) {
HebrewCalendar *hc = (HebrewCalendar*)&cal;
if (cal.isSet(UCAL_YEAR)) {
UErrorCode monthStatus = U_ZERO_ERROR;
Expand Down Expand Up @@ -3852,7 +3858,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, ch
switch (patternCharIndex) {
case UDAT_MONTH_FIELD:
// See notes under UDAT_MONTH_FIELD case above
if (!strcmp(cal.getType(),"hebrew")) {
if (typeid(cal) == typeid(HebrewCalendar)) {
HebrewCalendar *hc = (HebrewCalendar*)&cal;
if (cal.isSet(UCAL_YEAR)) {
UErrorCode monthStatus = U_ZERO_ERROR;
Expand Down Expand Up @@ -4034,7 +4040,7 @@ SimpleDateFormat::applyPattern(const UnicodeString& pattern)

// Hack to update use of Gannen year numbering for ja@calendar=japanese -
// use only if format is non-numeric (includes 年) and no other fDateOverride.
if (fCalendar != nullptr && uprv_strcmp(fCalendar->getType(),"japanese") == 0 &&
if (fCalendar != nullptr && typeid(*fCalendar) == typeid(JapaneseCalendar) &&
uprv_strcmp(fLocale.getLanguage(),"ja") == 0) {
if (fDateOverride==UnicodeString(u"y=jpanyear") && !fHasHanYearChar) {
// Gannen numbering is set but new pattern should not use it, unset;
Expand Down
5 changes: 3 additions & 2 deletions icu4c/source/i18n/windtfmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
# define NOIME
# define NOMCX
#include <windows.h>
#include <typeinfo>

U_NAMESPACE_BEGIN

Expand Down Expand Up @@ -251,7 +252,7 @@ UnicodeString &Win32DateFormat::format(Calendar &cal, UnicodeString &appendTo, F
formatDate(&st_local, date);
formatTime(&st_local, time);

if (strcmp(fCalendar->getType(), cal.getType()) != 0) {
if (typeid(cal) != typeid(*fCalendar)) {
pattern = getTimeDateFormat(&cal, &fLocale, status);
}

Expand All @@ -272,7 +273,7 @@ void Win32DateFormat::parse(const UnicodeString& /* text */, Calendar& /* cal */

void Win32DateFormat::adoptCalendar(Calendar *newCalendar)
{
if (fCalendar == nullptr || strcmp(fCalendar->getType(), newCalendar->getType()) != 0) {
if (fCalendar == nullptr || typeid(*fCalendar) != typeid(*newCalendar)) {
UErrorCode status = U_ZERO_ERROR;

if (fDateStyle != DateFormat::kNone && fTimeStyle != DateFormat::kNone) {
Expand Down

0 comments on commit ede201c

Please sign in to comment.