diff --git a/icu4c/source/common/brkiter.cpp b/icu4c/source/common/brkiter.cpp index 44a13ee6a2ac..6ef4b45217b4 100644 --- a/icu4c/source/common/brkiter.cpp +++ b/icu4c/source/common/brkiter.cpp @@ -121,10 +121,8 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st // If there is a result, set the valid locale and actual locale, and the kind if (U_SUCCESS(status) && result != nullptr) { - U_LOCALE_BASED(locBased, *(BreakIterator*)result); - - locBased.setLocaleIDs(ures_getLocaleByType(b, ULOC_VALID_LOCALE, &status), - actual.data(), status); + result->setLocaleIDs(ures_getLocaleByType(b, ULOC_VALID_LOCALE, &status), + actual.data()); LocaleBased::setLocaleID(loc.getName(), result->requestLocale, status); } @@ -207,19 +205,17 @@ BreakIterator::BreakIterator() { } -BreakIterator::BreakIterator(const BreakIterator &other) : UObject(other) { +BreakIterator::BreakIterator(const BreakIterator &other) : UObject(other), DataLocaleInformation(other) { UErrorCode status = U_ZERO_ERROR; - U_LOCALE_BASED(locBased, *this); - locBased.setLocaleIDs(other.validLocale, other.actualLocale, status); LocaleBased::setLocaleID(other.requestLocale, requestLocale, status); U_ASSERT(U_SUCCESS(status)); } + BreakIterator &BreakIterator::operator =(const BreakIterator &other) { if (this != &other) { + DataLocaleInformation::operator=(other); UErrorCode status = U_ZERO_ERROR; - U_LOCALE_BASED(locBased, *this); - locBased.setLocaleIDs(other.validLocale, other.actualLocale, status); LocaleBased::setLocaleID(other.requestLocale, requestLocale, status); U_ASSERT(U_SUCCESS(status)); } @@ -228,8 +224,6 @@ BreakIterator &BreakIterator::operator =(const BreakIterator &other) { BreakIterator::~BreakIterator() { - delete validLocale; - delete actualLocale; delete requestLocale; } @@ -398,8 +392,7 @@ BreakIterator::createInstance(const Locale& loc, int32_t kind, UErrorCode& statu // THIS LONG is a sign of bad code -- so the action item is to // revisit this in ICU 3.0 and clean it up/fix it/remove it. if (U_SUCCESS(status) && (result != nullptr) && *actualLoc.getName() != 0) { - U_LOCALE_BASED(locBased, *result); - locBased.setLocaleIDs(actualLoc.getName(), actualLoc.getName(), status); + result->setLocaleIDs(actualLoc.getName(), actualLoc.getName()); } return result; } @@ -509,7 +502,7 @@ BreakIterator::getLocale(ULocDataLocaleType type, UErrorCode& status) const { return requestLocale == nullptr ? Locale::getRoot() : Locale(requestLocale->data()); } - return LocaleBased::getLocale(validLocale, actualLocale, type, status); + return DataLocaleInformation::getLocale(type, status); } const char * @@ -520,10 +513,9 @@ BreakIterator::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { if (type == ULOC_REQUESTED_LOCALE) { return requestLocale == nullptr ? "" : requestLocale->data(); } - return LocaleBased::getLocaleID(validLocale, actualLocale, type, status); + return DataLocaleInformation::getLocaleID(type, status); } - // This implementation of getRuleStatus is a do-nothing stub, here to // provide a default implementation for any derived BreakIterator classes that // do not implement it themselves. @@ -547,10 +539,7 @@ int32_t BreakIterator::getRuleStatusVec(int32_t *fillInVec, int32_t capacity, UE } BreakIterator::BreakIterator (const Locale& valid, const Locale& actual) { - UErrorCode status = U_ZERO_ERROR; - U_LOCALE_BASED(locBased, (*this)); - locBased.setLocaleIDs(valid.getName(), actual.getName(), status); - U_ASSERT(U_SUCCESS(status)); + setLocaleIDs(valid.getName(), actual.getName()); } U_NAMESPACE_END diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp index 4a73f5592052..27132c5bd742 100644 --- a/icu4c/source/common/locid.cpp +++ b/icu4c/source/common/locid.cpp @@ -58,6 +58,7 @@ #include "uniquecharstr.h" #include "ustr_imp.h" #include "uvector.h" +#include "locbased.h" U_NAMESPACE_BEGIN @@ -2729,5 +2730,41 @@ Locale::getBaseName() const { Locale::Iterator::~Iterator() = default; +DataLocaleInformation::DataLocaleInformation(const DataLocaleInformation& other) { + UErrorCode status = U_ZERO_ERROR; + actualLocale = other.actualLocale == nullptr ? nullptr : new CharString(*other.actualLocale, status); + validLocale = other.validLocale == nullptr ? nullptr : new CharString(*other.validLocale, status); + U_ASSERT(U_SUCCESS(status)); +} +DataLocaleInformation::~DataLocaleInformation() { + delete actualLocale; + delete validLocale; +} + +Locale DataLocaleInformation::getLocale(ULocDataLocaleType type, UErrorCode& status) const { + return LocaleBased::getLocale(validLocale, actualLocale, type, status); +} + +const char* DataLocaleInformation::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { + return LocaleBased::getLocaleID(validLocale, actualLocale, type, status); +} + +void DataLocaleInformation::setLocaleIDs(const char* valid, const char* actual) { + UErrorCode status = U_ZERO_ERROR; + U_LOCALE_BASED(locBased, *this); + locBased.setLocaleIDs(valid, actual, status); + U_ASSERT(U_SUCCESS(status)); +} + +DataLocaleInformation& DataLocaleInformation::operator=(const DataLocaleInformation& other) { + delete actualLocale; + delete validLocale; + UErrorCode status = U_ZERO_ERROR; + actualLocale = other.actualLocale == nullptr ? nullptr : new CharString(*other.actualLocale, status); + validLocale = other.validLocale == nullptr ? nullptr : new CharString(*other.validLocale, status); + U_ASSERT(U_SUCCESS(status)); + return *this; +} + //eof U_NAMESPACE_END diff --git a/icu4c/source/common/unicode/brkiter.h b/icu4c/source/common/unicode/brkiter.h index d953925bd72a..339bc9b23c71 100644 --- a/icu4c/source/common/unicode/brkiter.h +++ b/icu4c/source/common/unicode/brkiter.h @@ -105,7 +105,7 @@ class CharString; * and in the sample program icu/source/samples/break/break.cpp * */ -class U_COMMON_API BreakIterator : public UObject { +class U_COMMON_API BreakIterator : public UObject , public DataLocaleInformation { public: /** * destructor @@ -584,7 +584,7 @@ class U_COMMON_API BreakIterator : public UObject { * actual locale. * @stable ICU 2.8 */ - Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const; + Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const override; #ifndef U_HIDE_INTERNAL_API /** Get the locale for this break iterator object. You can choose between valid and actual locale. @@ -648,8 +648,6 @@ class U_COMMON_API BreakIterator : public UObject { private: /** @internal (private) */ - CharString* actualLocale = nullptr; - CharString* validLocale = nullptr; CharString* requestLocale = nullptr; }; diff --git a/icu4c/source/common/unicode/locid.h b/icu4c/source/common/unicode/locid.h index e1afd598cf9b..353953c831f4 100644 --- a/icu4c/source/common/unicode/locid.h +++ b/icu4c/source/common/unicode/locid.h @@ -55,6 +55,7 @@ void U_CALLCONV locale_available_init(); /**< @internal */ class StringEnumeration; class UnicodeString; +class CharString; /** * A Locale object represents a specific geographical, political, @@ -1283,6 +1284,63 @@ Locale::isBogus() const { return fIsBogus; } +/** + * DataLocaleInformation is an abstract base class for objects + * that perform getLocale operations to query locale data resolution. + */ +class U_COMMON_API DataLocaleInformation : public UMemory { +public: + DataLocaleInformation() = default; + + /** + * Initializes a DataLocaleInformation object from another + * DataLocaleInformation object. + * + * @param other The DataLocaleInformation object being copied in. + */ + DataLocaleInformation(const DataLocaleInformation& other); + + virtual ~DataLocaleInformation(); + + /** + * Set the locale meta-data for the service object wrapped by this + * object. If either parameter is zero, it is ignored. + * @param valid the ID of the valid locale + * @param actual the ID of the actual locale + */ + virtual void setLocaleIDs(const char* valid, const char* actual); + + /** Get the locale for this object. You can choose between valid and actual locale. + * @param type type of the locale we're looking for (valid or actual) + * @param status error code for the operation + * @return the locale + */ + virtual Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const; + +#ifndef U_HIDE_INTERNAL_API + /** Get the locale for this object. You can choose between valid and actual locale. + * @param type type of the locale we're looking for (valid or actual) + * @param status error code for the operation + * @return the locale + * @internal + */ + const char* getLocaleID(ULocDataLocaleType type, UErrorCode &status) const; +#endif /* U_HIDE_INTERNAL_API */ + + /** + * Replaces the entire contents of *this with the specified value. + * + * @param other The DataLocaleInformation object being copied in. + * @return *this + */ + DataLocaleInformation& operator=(const DataLocaleInformation& other); + + +private: + CharString* validLocale = nullptr; + CharString* actualLocale = nullptr; +}; + U_NAMESPACE_END #endif /* U_SHOW_CPLUSPLUS_API */ diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp index 167d8644827a..8281fedbb6df 100644 --- a/icu4c/source/i18n/calendar.cpp +++ b/icu4c/source/i18n/calendar.cpp @@ -774,14 +774,12 @@ fSkippedWallTime(UCAL_WALLTIME_LAST) Calendar::~Calendar() { delete fZone; - delete actualLocale; - delete validLocale; } // ------------------------------------- Calendar::Calendar(const Calendar &source) -: UObject(source) +: UObject(source), DataLocaleInformation(source) { *this = source; } @@ -792,6 +790,7 @@ Calendar & Calendar::operator=(const Calendar &right) { if (this != &right) { + DataLocaleInformation::operator=(right); uprv_arrayCopy(right.fFields, fFields, UCAL_FIELD_COUNT); uprv_arrayCopy(right.fStamp, fStamp, UCAL_FIELD_COUNT); fTime = right.fTime; @@ -814,10 +813,6 @@ Calendar::operator=(const Calendar &right) fWeekendCease = right.fWeekendCease; fWeekendCeaseMillis = right.fWeekendCeaseMillis; fNextStamp = right.fNextStamp; - UErrorCode status = U_ZERO_ERROR; - U_LOCALE_BASED(locBased, *this); - locBased.setLocaleIDs(right.validLocale, right.actualLocale, status); - U_ASSERT(U_SUCCESS(status)); } return *this; @@ -4109,9 +4104,8 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode& } if (U_SUCCESS(status)) { - U_LOCALE_BASED(locBased,*this); - locBased.setLocaleIDs(ures_getLocaleByType(monthNames.getAlias(), ULOC_VALID_LOCALE, &status), - ures_getLocaleByType(monthNames.getAlias(), ULOC_ACTUAL_LOCALE, &status), status); + setLocaleIDs(ures_getLocaleByType(monthNames.getAlias(), ULOC_VALID_LOCALE, &status), + ures_getLocaleByType(monthNames.getAlias(), ULOC_ACTUAL_LOCALE, &status)); } else { status = U_USING_FALLBACK_WARNING; return; @@ -4197,16 +4191,6 @@ Calendar::updateTime(UErrorCode& status) fAreFieldsVirtuallySet = false; } -Locale -Calendar::getLocale(ULocDataLocaleType type, UErrorCode& status) const { - return LocaleBased::getLocale(validLocale, actualLocale, type, status); -} - -const char * -Calendar::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { - return LocaleBased::getLocaleID(validLocale, actualLocale, type, status); -} - void Calendar::recalculateStamp() { int32_t index; diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp index 339db48dba85..aa8df6f0d8db 100644 --- a/icu4c/source/i18n/dtfmtsym.cpp +++ b/icu4c/source/i18n/dtfmtsym.cpp @@ -318,7 +318,7 @@ DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status) } DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other) - : UObject(other) + : UObject(other), DataLocaleInformation(other) { copyData(other); } @@ -400,10 +400,6 @@ DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings) */ void DateFormatSymbols::copyData(const DateFormatSymbols& other) { - UErrorCode status = U_ZERO_ERROR; - U_LOCALE_BASED(locBased, *this); - locBased.setLocaleIDs(other.validLocale, other.actualLocale, status); - U_ASSERT(U_SUCCESS(status)); assignArray(fEras, fErasCount, other.fEras, other.fErasCount); assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount); assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount); @@ -487,6 +483,7 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) { DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other) { if (this == &other) { return *this; } // self-assignment: no-op + DataLocaleInformation::operator=(other); dispose(); copyData(other); @@ -496,8 +493,6 @@ DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other) DateFormatSymbols::~DateFormatSymbols() { dispose(); - delete actualLocale; - delete validLocale; } void DateFormatSymbols::dispose() @@ -537,10 +532,6 @@ void DateFormatSymbols::dispose() delete[] fStandaloneWideDayPeriods; delete[] fStandaloneNarrowDayPeriods; - delete actualLocale; - actualLocale = nullptr; - delete validLocale; - validLocale = nullptr; disposeZoneStrings(); } @@ -2302,12 +2293,11 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError } } - U_LOCALE_BASED(locBased, *this); // 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(ures_getLocaleByType(cb.getAlias(), ULOC_VALID_LOCALE, &status), - ures_getLocaleByType(cb.getAlias(), ULOC_ACTUAL_LOCALE, &status), status); + setLocaleIDs(ures_getLocaleByType(cb.getAlias(), ULOC_VALID_LOCALE, &status), + ures_getLocaleByType(cb.getAlias(), ULOC_ACTUAL_LOCALE, &status)); // Load eras initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status); @@ -2531,11 +2521,6 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError } } -Locale -DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { - return LocaleBased::getLocale(validLocale, actualLocale, type, status); -} - U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/format.cpp b/icu4c/source/i18n/format.cpp index b4aec1d98115..c523e22f4723 100644 --- a/icu4c/source/i18n/format.cpp +++ b/icu4c/source/i18n/format.cpp @@ -79,15 +79,13 @@ Format::Format() Format::~Format() { - delete actualLocale; - delete validLocale; } // ------------------------------------- // copy constructor Format::Format(const Format &that) - : UObject(that) + : UObject(that), DataLocaleInformation(that) { *this = that; } @@ -99,10 +97,7 @@ Format& Format::operator=(const Format& that) { if (this != &that) { - UErrorCode status = U_ZERO_ERROR; - U_LOCALE_BASED(locBased, *this); - locBased.setLocaleIDs(that.validLocale, that.actualLocale, status); - U_ASSERT(U_SUCCESS(status)); + DataLocaleInformation::operator=(that); } return *this; } @@ -198,24 +193,6 @@ void Format::syntaxError(const UnicodeString& pattern, parseError.postContext[stop-start]= 0; } -Locale -Format::getLocale(ULocDataLocaleType type, UErrorCode& status) const { - return LocaleBased::getLocale(validLocale, actualLocale, type, status); -} - -const char * -Format::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { - return LocaleBased::getLocaleID(validLocale,actualLocale, type, status); -} - -void -Format::setLocaleIDs(const char* valid, const char* actual) { - U_LOCALE_BASED(locBased, *this); - UErrorCode status = U_ZERO_ERROR; - locBased.setLocaleIDs(valid, actual, status); - U_ASSERT(U_SUCCESS(status)); -} - U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/unicode/calendar.h b/icu4c/source/i18n/unicode/calendar.h index 208ab7643ee5..0dcbf36997a0 100644 --- a/icu4c/source/i18n/unicode/calendar.h +++ b/icu4c/source/i18n/unicode/calendar.h @@ -55,7 +55,6 @@ class ICUServiceFactory; typedef int32_t UFieldResolutionTable[12][8]; class BasicTimeZone; -class CharString; /** * `Calendar` is an abstract base class for converting between * a `UDate` object and a set of integer fields such as @@ -187,7 +186,7 @@ class CharString; * * @stable ICU 2.0 */ -class U_I18N_API Calendar : public UObject { +class U_I18N_API Calendar : public UObject , public DataLocaleInformation { public: #ifndef U_FORCE_HIDE_DEPRECATED_API /** @@ -2343,10 +2342,6 @@ class U_I18N_API Calendar : public UObject { static uint8_t julianDayToDayOfWeek(int32_t julian); #endif /* U_HIDE_INTERNAL_API */ - private: - CharString* validLocale = nullptr; - CharString* actualLocale = nullptr; - public: #if !UCONFIG_NO_SERVICE /** @@ -2431,14 +2426,6 @@ class U_I18N_API Calendar : public UObject { */ virtual int32_t defaultCenturyStartYear() const = 0; - /** Get the locale for this calendar object. You can choose between valid and actual locale. - * @param type type of the locale we're looking for (valid or actual) - * @param status error code for the operation - * @return the locale - * @stable ICU 2.8 - */ - Locale getLocale(ULocDataLocaleType type, UErrorCode &status) const; - /** * @return The related Gregorian year; will be obtained by modifying the value * obtained by get from UCAL_EXTENDED_YEAR field @@ -2453,16 +2440,6 @@ class U_I18N_API Calendar : public UObject { */ virtual void setRelatedYear(int32_t year); -#ifndef U_HIDE_INTERNAL_API - /** Get the locale for this calendar object. You can choose between valid and actual locale. - * @param type type of the locale we're looking for (valid or actual) - * @param status error code for the operation - * @return the locale - * @internal - */ - const char* getLocaleID(ULocDataLocaleType type, UErrorCode &status) const; -#endif /* U_HIDE_INTERNAL_API */ - private: /** * Cast TimeZone used by this object to BasicTimeZone, or nullptr if the TimeZone diff --git a/icu4c/source/i18n/unicode/dtfmtsym.h b/icu4c/source/i18n/unicode/dtfmtsym.h index 18e2641b588f..a394593bbf89 100644 --- a/icu4c/source/i18n/unicode/dtfmtsym.h +++ b/icu4c/source/i18n/unicode/dtfmtsym.h @@ -82,7 +82,7 @@ class CharString; * locale at least contains any resources that are to be particularized for the * calendar type. */ -class U_I18N_API DateFormatSymbols final : public UObject { +class U_I18N_API DateFormatSymbols final : public UObject, public DataLocaleInformation { public: /** * Construct a DateFormatSymbols object by loading format data from @@ -590,13 +590,6 @@ class U_I18N_API DateFormatSymbols final : public UObject { */ void setLocalPatternChars(const UnicodeString& newLocalPatternChars); - /** - * Returns the locale for this object. Two flavors are available: - * valid and actual locale. - * @stable ICU 2.8 - */ - Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const; - /* The following type and kCapContextUsageTypeCount cannot be #ifndef U_HIDE_INTERNAL_API, they are needed for .h file declarations. */ /** @@ -915,12 +908,6 @@ class U_I18N_API DateFormatSymbols final : public UObject { int32_t fStandaloneNarrowDayPeriodsCount; private: - /** valid/actual locale information - * these are always ICU locales, so the length should not be a problem - */ - CharString* validLocale = nullptr; - CharString* actualLocale = nullptr; - DateFormatSymbols() = delete; // default constructor not implemented /** diff --git a/icu4c/source/i18n/unicode/format.h b/icu4c/source/i18n/unicode/format.h index 3d435f0de7e3..cd92e23cf875 100644 --- a/icu4c/source/i18n/unicode/format.h +++ b/icu4c/source/i18n/unicode/format.h @@ -96,7 +96,7 @@ class CharString; * subclasses, such code will not necessarily work and will not be * guaranteed to work stably from release to release. */ -class U_I18N_API Format : public UObject { +class U_I18N_API Format : public UObject, public DataLocaleInformation { public: /** Destructor @@ -245,28 +245,6 @@ class U_I18N_API Format : public UObject { Formattable& result, UErrorCode& status) const; - /** Get the locale for this format object. You can choose between valid and actual locale. - * @param type type of the locale we're looking for (valid or actual) - * @param status error code for the operation - * @return the locale - * @stable ICU 2.8 - */ - Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const; - -#ifndef U_HIDE_INTERNAL_API - /** Get the locale for this format object. You can choose between valid and actual locale. - * @param type type of the locale we're looking for (valid or actual) - * @param status error code for the operation - * @return the locale - * @internal - */ - const char* getLocaleID(ULocDataLocaleType type, UErrorCode &status) const; -#endif /* U_HIDE_INTERNAL_API */ - - protected: - /** @stable ICU 2.8 */ - void setLocaleIDs(const char* valid, const char* actual); - protected: /** * Default constructor for subclass use only. Does nothing. @@ -296,10 +274,6 @@ class U_I18N_API Format : public UObject { static void syntaxError(const UnicodeString& pattern, int32_t pos, UParseError& parseError); - - private: - CharString* actualLocale = nullptr; - CharString* validLocale = nullptr; }; U_NAMESPACE_END diff --git a/icu4c/source/i18n/unicode/measfmt.h b/icu4c/source/i18n/unicode/measfmt.h index c9894f0b5916..d3d8d8601158 100644 --- a/icu4c/source/i18n/unicode/measfmt.h +++ b/icu4c/source/i18n/unicode/measfmt.h @@ -342,6 +342,9 @@ class U_I18N_API MeasureFormat : public Format { */ const PluralRules &getPluralRules() const; + using DataLocaleInformation::getLocale; + using DataLocaleInformation::getLocaleID; + /** * ICU use only. * @internal. diff --git a/icu4c/source/i18n/unicode/msgfmt.h b/icu4c/source/i18n/unicode/msgfmt.h index cb47ba48780e..c43d6940a396 100644 --- a/icu4c/source/i18n/unicode/msgfmt.h +++ b/icu4c/source/i18n/unicode/msgfmt.h @@ -438,6 +438,7 @@ class U_I18N_API MessageFormat : public Format { */ virtual void setLocale(const Locale& theLocale); + using DataLocaleInformation::getLocale; /** * Gets the locale used for creating argument Format objects. * format information.