From: Shane Carr Date: Tue, 13 Mar 2018 09:25:41 +0000 (+0000) Subject: ICU-13634 Adding new field structure to DecimalFormat and wiring up constructors. X-Git-Tag: release-62-rc~200^2~99 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8a50c335fa62ad127d51b9b08c6a5acafc7a1992;p=icu ICU-13634 Adding new field structure to DecimalFormat and wiring up constructors. X-SVN-Rev: 41099 --- diff --git a/icu4c/source/i18n/Makefile.in b/icu4c/source/i18n/Makefile.in index 83c0e3c69d4..a1d186b4350 100644 --- a/icu4c/source/i18n/Makefile.in +++ b/icu4c/source/i18n/Makefile.in @@ -107,7 +107,8 @@ double-conversion.o double-conversion-bignum-dtoa.o double-conversion-bignum.o \ double-conversion-cached-powers.o double-conversion-diy-fp.o double-conversion-fast-dtoa.o \ numparse_stringsegment.o numparse_unisets.o numparse_parsednumber.o \ numparse_impl.o numparse_symbols.o numparse_decimal.o numparse_scientific.o \ -numparse_currency.o numparse_affixes.o numparse_compositions.o +numparse_currency.o numparse_affixes.o numparse_compositions.o \ +number_mapper.o ## Header files to install diff --git a/icu4c/source/i18n/decimfmt.cpp b/icu4c/source/i18n/decimfmt.cpp index dac10b80a77..ca2eb5ca069 100644 --- a/icu4c/source/i18n/decimfmt.cpp +++ b/icu4c/source/i18n/decimfmt.cpp @@ -9,25 +9,67 @@ // Helpful in toString methods and elsewhere. #define UNISTR_FROM_STRING_EXPLICIT +#include "unicode/errorcode.h" #include "unicode/decimfmt.h" #include "number_decimalquantity.h" +#include "number_types.h" +#include "numparse_impl.h" +#include "number_mapper.h" +#include "number_patternstring.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; +using namespace icu::numparse; +using namespace icu::numparse::impl; using ERoundingMode = icu::DecimalFormat::ERoundingMode; using EPadPosition = icu::DecimalFormat::EPadPosition; -DecimalFormat::DecimalFormat(UErrorCode& status) {} +DecimalFormat::DecimalFormat(UErrorCode& status) + : DecimalFormat(nullptr, status) { +} -DecimalFormat::DecimalFormat(const UnicodeString& pattern, UErrorCode& status) {} +DecimalFormat::DecimalFormat(const UnicodeString& pattern, UErrorCode& status) + : DecimalFormat(nullptr, status) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + refreshFormatter(status); +} DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt, - UErrorCode& status) {} + UErrorCode& status) + : DecimalFormat(symbolsToAdopt, status) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); +} DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt, - UNumberFormatStyle style, UErrorCode& status) {} + UNumberFormatStyle style, UErrorCode& status) + : DecimalFormat(symbolsToAdopt, status) { + // If choice is a currency type, ignore the rounding information. + if (style == UNumberFormatStyle::UNUM_CURRENCY || style == UNumberFormatStyle::UNUM_CURRENCY_ISO || + style == UNumberFormatStyle::UNUM_CURRENCY_ACCOUNTING || + style == UNumberFormatStyle::UNUM_CASH_CURRENCY || + style == UNumberFormatStyle::UNUM_CURRENCY_STANDARD || + style == UNumberFormatStyle::UNUM_CURRENCY_PLURAL) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_ALWAYS, status); + } else { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + } + refreshFormatter(status); +} + +DecimalFormat::DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorCode& status) { + properties = new DecimalFormatProperties(); + exportedProperties = new DecimalFormatProperties(); + if (symbolsToAdopt == nullptr) { + symbols = new DecimalFormatSymbols(status); + } else { + symbols = symbolsToAdopt; + } + if (properties == nullptr || exportedProperties == nullptr || symbols == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } +} void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {} @@ -43,12 +85,30 @@ void DecimalFormat::setParseIntegerOnly(UBool value) {} void DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) {} DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt, - UParseError& parseError, UErrorCode& status) {} + UParseError& parseError, UErrorCode& status) + : DecimalFormat(symbolsToAdopt, status) { + // TODO: What is parseError for? + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + refreshFormatter(status); +} DecimalFormat::DecimalFormat(const UnicodeString& pattern, const DecimalFormatSymbols& symbols, - UErrorCode& status) {} - -DecimalFormat::DecimalFormat(const DecimalFormat& source) {} + UErrorCode& status) + : DecimalFormat(new DecimalFormatSymbols(symbols), status) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + refreshFormatter(status); +} + +DecimalFormat::DecimalFormat(const DecimalFormat& source) { + properties = new DecimalFormatProperties(); + exportedProperties = new DecimalFormatProperties(); + symbols = new DecimalFormatSymbols(*source.symbols); + if (properties == nullptr || exportedProperties == nullptr || symbols == nullptr) { + return; + } + ErrorCode localStatus; + refreshFormatter(localStatus); +} DecimalFormat& DecimalFormat::operator=(const DecimalFormat& rhs) {} @@ -239,5 +299,39 @@ UClassID DecimalFormat::getStaticClassID() {} UClassID DecimalFormat::getDynamicClassID() const {} +/** Rebuilds the formatter object from the property bag. */ +void DecimalFormat::refreshFormatter(UErrorCode& status) { + if (exportedProperties == nullptr) { + // exportedProperties is null only when the formatter is not ready yet. + // The only time when this happens is during legacy deserialization. + return; + } + Locale locale = getLocale(ULOC_ACTUAL_LOCALE, status); + if (U_FAILURE(status)) { + // Constructor + locale = symbols->getLocale(ULOC_ACTUAL_LOCALE, status); + } + if (U_FAILURE(status)) { + // Deserialization + locale = symbols->getLocale(); + } + if (U_FAILURE(status)) { + return; + } + + *formatter = NumberPropertyMapper::create(*properties, *symbols, *exportedProperties, status).locale( + locale); + parser = NumberParserImpl::createParserFromProperties(*properties, *symbols, false, false, status); + parserWithCurrency = NumberParserImpl::createParserFromProperties( + *properties, *symbols, true, false, status); +} + +void DecimalFormat::setPropertiesFromPattern(const UnicodeString& pattern, int32_t ignoreRounding, + UErrorCode& status) { + // Cast workaround to get around putting the enum in the public header file + auto actualIgnoreRounding = static_cast(ignoreRounding); + PatternParser::parseToExistingProperties(pattern, *properties, actualIgnoreRounding, status); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/number_fluent.cpp b/icu4c/source/i18n/number_fluent.cpp index 27113106c50..190b94bf159 100644 --- a/icu4c/source/i18n/number_fluent.cpp +++ b/icu4c/source/i18n/number_fluent.cpp @@ -139,6 +139,13 @@ Derived NumberFormatterSettings::threshold(int32_t threshold) const { return copy; } +template +Derived NumberFormatterSettings::macros(impl::MacroProps& macros) const { + Derived copy(*this); + copy.fMacros = macros; + return copy; +} + // Declare all classes that implement NumberFormatterSettings // See https://stackoverflow.com/a/495056/1407170 template diff --git a/icu4c/source/i18n/number_mapper.cpp b/icu4c/source/i18n/number_mapper.cpp new file mode 100644 index 00000000000..ac8cda356f6 --- /dev/null +++ b/icu4c/source/i18n/number_mapper.cpp @@ -0,0 +1,23 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT + +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT + +#include "number_mapper.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + + + + + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/number_mapper.h b/icu4c/source/i18n/number_mapper.h new file mode 100644 index 00000000000..c3960a665be --- /dev/null +++ b/icu4c/source/i18n/number_mapper.h @@ -0,0 +1,63 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#ifndef __NUMBER_MAPPER_H__ +#define __NUMBER_MAPPER_H__ + +#include "number_types.h" + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + + +/** + * Utilities for converting between a DecimalFormatProperties and a MacroProps. + */ +class NumberPropertyMapper { + public: + /** Convenience method to create a NumberFormatter directly from Properties. */ + static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, UErrorCode& status); + + /** Convenience method to create a NumberFormatter directly from Properties. */ + static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, + DecimalFormatProperties& exportedProperties, + UErrorCode& status); + + /** + * Convenience method to create a NumberFormatter directly from a pattern string. Something like this + * could become public API if there is demand. + */ + static UnlocalizedNumberFormatter create(const UnicodeString& pattern, + const DecimalFormatSymbols& symbols, UErrorCode& status); + + /** + * Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties} + * object. In other words, maps Properties to MacroProps. This function is used by the + * JDK-compatibility API to call into the ICU 60 fluent number formatting pipeline. + * + * @param properties + * The property bag to be mapped. + * @param symbols + * The symbols associated with the property bag. + * @param exportedProperties + * A property bag in which to store validated properties. Used by some DecimalFormat + * getters. + * @return A new MacroProps containing all of the information in the Properties. + */ + static void oldToNew(const DecimalFormatProperties& properties, const DecimalFormatSymbols& symbols, + DecimalFormatProperties& exportedProperties, MacroProps& output, + UErrorCode& status); +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMBER_MAPPER_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/number_patternstring.h b/icu4c/source/i18n/number_patternstring.h index 0a343f63782..d0e62ef21f4 100644 --- a/icu4c/source/i18n/number_patternstring.h +++ b/icu4c/source/i18n/number_patternstring.h @@ -139,6 +139,10 @@ struct U_I18N_API ParsedPatternInfo : public AffixPatternProvider, public UMemor friend class PatternParser; }; +enum IgnoreRounding { + IGNORE_ROUNDING_NEVER = 0, IGNORE_ROUNDING_IF_CURRENCY = 1, IGNORE_ROUNDING_ALWAYS = 2 +}; + class U_I18N_API PatternParser { public: /** @@ -157,10 +161,6 @@ class U_I18N_API PatternParser { static void parseToPatternInfo(const UnicodeString& patternString, ParsedPatternInfo& patternInfo, UErrorCode& status); - enum IgnoreRounding { - IGNORE_ROUNDING_NEVER = 0, IGNORE_ROUNDING_IF_CURRENCY = 1, IGNORE_ROUNDING_ALWAYS = 2 - }; - /** * Parses a pattern string into a new property bag. * diff --git a/icu4c/source/i18n/numparse_impl.h b/icu4c/source/i18n/numparse_impl.h index 210dcf47549..901c226a13b 100644 --- a/icu4c/source/i18n/numparse_impl.h +++ b/icu4c/source/i18n/numparse_impl.h @@ -14,6 +14,7 @@ #include "unicode/uniset.h" #include "numparse_currency.h" #include "numparse_affixes.h" +#include "number_decimfmtprops.h" U_NAMESPACE_BEGIN namespace numparse { namespace impl { @@ -25,6 +26,10 @@ class NumberParserImpl : public MutableMatcherCollection { static NumberParserImpl* createSimpleParser(const Locale& locale, const UnicodeString& patternString, parse_flags_t parseFlags, UErrorCode& status); + static NumberParserImpl* createParserFromProperties( + const number::impl::DecimalFormatProperties& properties, DecimalFormatSymbols symbols, + bool parseCurrency, bool optimize, UErrorCode& status); + void addMatcher(NumberParseMatcher& matcher) override; void freeze(); diff --git a/icu4c/source/i18n/unicode/decimfmt.h b/icu4c/source/i18n/unicode/decimfmt.h index 1fe5d99d32e..b86c2ee4476 100644 --- a/icu4c/source/i18n/unicode/decimfmt.h +++ b/icu4c/source/i18n/unicode/decimfmt.h @@ -70,6 +70,13 @@ class VisibleDigitsWithExponent; namespace number { namespace impl { class DecimalQuantity; +struct DecimalFormatProperties; +} +} + +namespace numparse { +namespace impl { +class NumberParserImpl; } } @@ -679,17 +686,14 @@ template class U_I18N_API EnumSet