]> granicus.if.org Git - icu/commitdiff
ICU-13634 Adding new field structure to DecimalFormat and wiring up constructors.
authorShane Carr <shane@unicode.org>
Tue, 13 Mar 2018 09:25:41 +0000 (09:25 +0000)
committerShane Carr <shane@unicode.org>
Tue, 13 Mar 2018 09:25:41 +0000 (09:25 +0000)
X-SVN-Rev: 41099

icu4c/source/i18n/Makefile.in
icu4c/source/i18n/decimfmt.cpp
icu4c/source/i18n/number_fluent.cpp
icu4c/source/i18n/number_mapper.cpp [new file with mode: 0644]
icu4c/source/i18n/number_mapper.h [new file with mode: 0644]
icu4c/source/i18n/number_patternstring.h
icu4c/source/i18n/numparse_impl.h
icu4c/source/i18n/unicode/decimfmt.h
icu4c/source/i18n/unicode/numberformatter.h
icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatter.java
icu4j/main/classes/core/src/com/ibm/icu/number/NumberPropertyMapper.java

index 83c0e3c69d49faa4045c71e6aca3e47a8c5fcf4d..a1d186b43501db18f0608c136a419da609862453 100644 (file)
@@ -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
index dac10b80a77bceb3e5a042d4960bb711fb75d0bb..ca2eb5ca0693ad0ad5fe731b601e3cdb543e40f4 100644 (file)
@@ -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>(ignoreRounding);
+    PatternParser::parseToExistingProperties(pattern, *properties, actualIgnoreRounding, status);
+}
+
 
 #endif /* #if !UCONFIG_NO_FORMATTING */
index 27113106c5045117efdc9eb1d4a5e3a467df1d94..190b94bf15904b0ac35a35cbd920fd7040409568 100644 (file)
@@ -139,6 +139,13 @@ Derived NumberFormatterSettings<Derived>::threshold(int32_t threshold) const {
     return copy;
 }
 
+template<typename Derived>
+Derived NumberFormatterSettings<Derived>::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 (file)
index 0000000..ac8cda3
--- /dev/null
@@ -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 (file)
index 0000000..c3960a6
--- /dev/null
@@ -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 */
index 0a343f637821a7ca2c0a1bf8de08958383d9d293..d0e62ef21f45517d16e48c46f91ff2223ca00af6 100644 (file)
@@ -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.
      *
index 210dcf47549fa1afb7675ec99f7efa10755dd12f..901c226a13b6f68d4a56820127cee71b2531cfe1 100644 (file)
@@ -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();
index 1fe5d99d32e7e1036c3751e06854adbfa3183f15..b86c2ee44760c6cb9d07e11c3967585c1a307a82 100644 (file)
@@ -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<UNumberFormatAttribute,
  * subclasses, such code will not necessarily work and will not be
  * guaranteed to work stably from release to release.
  */
-class U_I18N_API DecimalFormat: public NumberFormat {
-public:
+class U_I18N_API DecimalFormat : public NumberFormat {
+  public:
     /**
      * Pad position.
      * @stable ICU 2.4
      */
     enum EPadPosition {
-        kPadBeforePrefix,
-        kPadAfterPrefix,
-        kPadBeforeSuffix,
-        kPadAfterSuffix
+        kPadBeforePrefix, kPadAfterPrefix, kPadBeforeSuffix, kPadAfterSuffix
     };
 
     /**
@@ -721,8 +725,7 @@ public:
      *                  pattern is invalid this will be set to a failure code.
      * @stable ICU 2.0
      */
-    DecimalFormat(const UnicodeString& pattern,
-                  UErrorCode& status);
+    DecimalFormat(const UnicodeString& pattern, UErrorCode& status);
 
     /**
      * Create a DecimalFormat from the given pattern and symbols.
@@ -742,11 +745,10 @@ public:
      *                          pattern is invalid this will be set to a failure code.
      * @stable ICU 2.0
      */
-    DecimalFormat(  const UnicodeString& pattern,
-                    DecimalFormatSymbols* symbolsToAdopt,
-                    UErrorCode& status);
+    DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt, UErrorCode& status);
 
 #ifndef U_HIDE_INTERNAL_API
+
     /**
      * This API is for ICU use only.
      * Create a DecimalFormat from the given pattern, symbols, and style.
@@ -759,16 +761,22 @@ public:
      *                          pattern is invalid this will be set to a failure code.
      * @internal
      */
-    DecimalFormat(  const UnicodeString& pattern,
-                    DecimalFormatSymbols* symbolsToAdopt,
-                    UNumberFormatStyle style,
-                    UErrorCode& status);
+    DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
+                  UNumberFormatStyle style, UErrorCode& status);
+
+    /**
+     * This API is for ICU use only.
+     * Default internal constructor for DecimalFormat.
+     */
+    DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorCode& status);
 
 #if UCONFIG_HAVE_PARSEALLINPUT
+
     /**
      * @internal
      */
     void setParseAllInput(UNumberFormatAttributeValue value);
+
 #endif
 
 #endif  /* U_HIDE_INTERNAL_API */
@@ -784,9 +792,7 @@ public:
      * @return *this - for chaining (example: format.setAttribute(...).setAttribute(...) )
      * @stable ICU 51
      */
-    virtual DecimalFormat& setAttribute( UNumberFormatAttribute attr,
-                                       int32_t newvalue,
-                                       UErrorCode &status);
+    virtual DecimalFormat& setAttribute(UNumberFormatAttribute attr, int32_t newvalue, UErrorCode& status);
 
     /**
      * Get an integer
@@ -797,8 +803,7 @@ public:
      * @return the attribute value. Undefined if there is an error.
      * @stable ICU 51
      */
-    virtual int32_t getAttribute( UNumberFormatAttribute attr,
-                                  UErrorCode &status) const;
+    virtual int32_t getAttribute(UNumberFormatAttribute attr, UErrorCode& status) const;
 
 
     /**
@@ -848,10 +853,9 @@ public:
      *                          pattern is invalid this will be set to a failure code.
      * @stable ICU 2.0
      */
-    DecimalFormat(  const UnicodeString& pattern,
-                    DecimalFormatSymbols* symbolsToAdopt,
-                    UParseError& parseError,
-                    UErrorCode& status);
+    DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
+                  UParseError& parseError, UErrorCode& status);
+
     /**
      * Create a DecimalFormat from the given pattern and symbols.
      * Use this constructor when you need to completely customize the
@@ -869,9 +873,7 @@ public:
      *                          pattern is invalid this will be set to a failure code.
      * @stable ICU 2.0
      */
-    DecimalFormat(  const UnicodeString& pattern,
-                    const DecimalFormatSymbols& symbols,
-                    UErrorCode& status);
+    DecimalFormat(const UnicodeString& pattern, const DecimalFormatSymbols& symbols, UErrorCode& status);
 
     /**
      * Copy constructor.
@@ -928,9 +930,7 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 2.0
      */
-    UnicodeString& format(double number,
-                          UnicodeString& appendTo,
-                          FieldPosition& pos) const U_OVERRIDE;
+    UnicodeString& format(double number, UnicodeString& appendTo, FieldPosition& pos) const U_OVERRIDE;
 
 
     /**
@@ -945,10 +945,8 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @internal
      */
-    UnicodeString& format(double number,
-                          UnicodeString& appendTo,
-                          FieldPosition& pos,
-                          UErrorCode &status) const U_OVERRIDE;
+    UnicodeString& format(double number, UnicodeString& appendTo, FieldPosition& pos,
+                          UErrorCode& status) const U_OVERRIDE;
 
     /**
      * Format a double or long number using base-10 representation.
@@ -963,9 +961,7 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 4.4
      */
-    UnicodeString& format(double number,
-                          UnicodeString& appendTo,
-                          FieldPositionIterator* posIter,
+    UnicodeString& format(double number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                           UErrorCode& status) const U_OVERRIDE;
 
     /**
@@ -979,9 +975,7 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 2.0
      */
-    UnicodeString& format(int32_t number,
-                          UnicodeString& appendTo,
-                          FieldPosition& pos) const U_OVERRIDE;
+    UnicodeString& format(int32_t number, UnicodeString& appendTo, FieldPosition& pos) const U_OVERRIDE;
 
     /**
      * Format a long number using base-10 representation.
@@ -994,10 +988,8 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @internal
      */
-    UnicodeString& format(int32_t number,
-                          UnicodeString& appendTo,
-                          FieldPosition& pos,
-                          UErrorCode &status) const U_OVERRIDE;
+    UnicodeString& format(int32_t number, UnicodeString& appendTo, FieldPosition& pos,
+                          UErrorCode& status) const U_OVERRIDE;
 
     /**
      * Format a long number using base-10 representation.
@@ -1012,9 +1004,7 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 4.4
      */
-    UnicodeString& format(int32_t number,
-                          UnicodeString& appendTo,
-                          FieldPositionIterator* posIter,
+    UnicodeString& format(int32_t number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                           UErrorCode& status) const U_OVERRIDE;
 
     /**
@@ -1028,9 +1018,7 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 2.8
      */
-    UnicodeString& format(int64_t number,
-                          UnicodeString& appendTo,
-                          FieldPosition& pos) const U_OVERRIDE;
+    UnicodeString& format(int64_t number, UnicodeString& appendTo, FieldPosition& pos) const U_OVERRIDE;
 
     /**
      * Format an int64 number using base-10 representation.
@@ -1043,10 +1031,8 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @internal
      */
-    UnicodeString& format(int64_t number,
-                          UnicodeString& appendTo,
-                          FieldPosition& pos,
-                          UErrorCode &status) const U_OVERRIDE;
+    UnicodeString& format(int64_t number, UnicodeString& appendTo, FieldPosition& pos,
+                          UErrorCode& status) const U_OVERRIDE;
 
     /**
      * Format an int64 number using base-10 representation.
@@ -1061,9 +1047,7 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 4.4
      */
-    UnicodeString& format(int64_t number,
-                          UnicodeString& appendTo,
-                          FieldPositionIterator* posIter,
+    UnicodeString& format(int64_t number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                           UErrorCode& status) const U_OVERRIDE;
 
     /**
@@ -1082,9 +1066,7 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 4.4
      */
-    UnicodeString& format(StringPiece number,
-                          UnicodeString& appendTo,
-                          FieldPositionIterator* posIter,
+    UnicodeString& format(StringPiece number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                           UErrorCode& status) const U_OVERRIDE;
 
 
@@ -1103,10 +1085,8 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @internal
      */
-    UnicodeString& format(const number::impl::DecimalQuantity &number,
-                          UnicodeString& appendTo,
-                          FieldPositionIterator* posIter,
-                          UErrorCode& status) const U_OVERRIDE;
+    UnicodeString& format(const number::impl::DecimalQuantity& number, UnicodeString& appendTo,
+                          FieldPositionIterator* posIter, UErrorCode& status) const U_OVERRIDE;
 
     /**
      * Format a decimal number.
@@ -1123,34 +1103,31 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @internal
      */
-    UnicodeString& format(const number::impl::DecimalQuantity &number,
-                          UnicodeString& appendTo,
-                          FieldPosition& pos,
-                          UErrorCode& status) const U_OVERRIDE;
+    UnicodeString& format(const number::impl::DecimalQuantity& number, UnicodeString& appendTo,
+                          FieldPosition& pos, UErrorCode& status) const U_OVERRIDE;
+
+    using NumberFormat::parse;
 
-   using NumberFormat::parse;
-
-   /**
-    * Parse the given string using this object's choices. The method
-    * does string comparisons to try to find an optimal match.
-    * If no object can be parsed, index is unchanged, and NULL is
-    * returned.  The result is returned as the most parsimonious
-    * type of Formattable that will accomodate all of the
-    * necessary precision.  For example, if the result is exactly 12,
-    * it will be returned as a long.  However, if it is 1.5, it will
-    * be returned as a double.
-    *
-    * @param text           The text to be parsed.
-    * @param result         Formattable to be set to the parse result.
-    *                       If parse fails, return contents are undefined.
-    * @param parsePosition  The position to start parsing at on input.
-    *                       On output, moved to after the last successfully
-    *                       parse character. On parse failure, does not change.
-    * @see Formattable
-    * @stable ICU 2.0
-    */
-    void parse(const UnicodeString& text,
-               Formattable& result,
+    /**
+     * Parse the given string using this object's choices. The method
+     * does string comparisons to try to find an optimal match.
+     * If no object can be parsed, index is unchanged, and NULL is
+     * returned.  The result is returned as the most parsimonious
+     * type of Formattable that will accomodate all of the
+     * necessary precision.  For example, if the result is exactly 12,
+     * it will be returned as a long.  However, if it is 1.5, it will
+     * be returned as a double.
+     *
+     * @param text           The text to be parsed.
+     * @param result         Formattable to be set to the parse result.
+     *                       If parse fails, return contents are undefined.
+     * @param parsePosition  The position to start parsing at on input.
+     *                       On output, moved to after the last successfully
+     *                       parse character. On parse failure, does not change.
+     * @see Formattable
+     * @stable ICU 2.0
+     */
+    void parse(const UnicodeString& text, Formattable& result,
                ParsePosition& parsePosition) const U_OVERRIDE;
 
     /**
@@ -1172,8 +1149,7 @@ public:
      *             the parsed currency; if parse fails, this is NULL.
      * @stable ICU 49
      */
-    CurrencyAmount* parseCurrency(const UnicodeString& text,
-                                  ParsePosition& pos) const U_OVERRIDE;
+    CurrencyAmount* parseCurrency(const UnicodeString& text, ParsePosition& pos) const U_OVERRIDE;
 
     /**
      * Returns the decimal format symbols, which is generally not changed
@@ -1427,7 +1403,7 @@ public:
      * @see #setPadPosition
      * @stable ICU 2.0
      */
-    virtual void setPadCharacter(const UnicodeString &padChar);
+    virtual void setPadCharacter(const UnicodeStringpadChar);
 
     /**
      * Get the position at which padding will take place.  This is the location
@@ -1634,7 +1610,7 @@ public:
 
 #endif  /* U_HIDE_INTERNAL_API */
 
-       /* Cannot use #ifndef U_HIDE_INTERNAL_API for the following draft method since it is virtual. */
+    /* Cannot use #ifndef U_HIDE_INTERNAL_API for the following draft method since it is virtual. */
     /**
      * Sets the minimum grouping digits. Setting to a value less than or
      * equal to 1 turns off minimum grouping digits.
@@ -1739,9 +1715,8 @@ public:
      *                   set to a failure result.
      * @stable ICU 2.0
      */
-    virtual void applyPattern(const UnicodeString& pattern,
-                              UParseError& parseError,
-                              UErrorCode& status);
+    virtual void applyPattern(const UnicodeString& pattern, UParseError& parseError, UErrorCode& status);
+
     /**
      * Sets the pattern.
      * @param pattern   The pattern to be applied.
@@ -1750,8 +1725,7 @@ public:
      *                  set to a failure result.
      * @stable ICU 2.0
      */
-    virtual void applyPattern(const UnicodeString& pattern,
-                              UErrorCode& status);
+    virtual void applyPattern(const UnicodeString& pattern, UErrorCode& status);
 
     /**
      * Apply the given pattern to this Format object.  The pattern
@@ -1783,8 +1757,7 @@ public:
      *                  set to a failure result.
      * @stable ICU 2.0
      */
-    virtual void applyLocalizedPattern(const UnicodeString& pattern,
-                                       UParseError& parseError,
+    virtual void applyLocalizedPattern(const UnicodeString& pattern, UParseError& parseError,
                                        UErrorCode& status);
 
     /**
@@ -1796,8 +1769,7 @@ public:
      *                  set to a failure result.
      * @stable ICU 2.0
      */
-    virtual void applyLocalizedPattern(const UnicodeString& pattern,
-                                       UErrorCode& status);
+    virtual void applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status);
 
 
     /**
@@ -1942,6 +1914,7 @@ public:
     UCurrencyUsage getCurrencyUsage() const;
 
 #ifndef U_HIDE_INTERNAL_API
+
     /**
      *  Format a number and save it into the given DecimalQuantity.
      *  Internal, not intended for public use.
@@ -1958,6 +1931,7 @@ public:
      */
     void formatToDecimalQuantity(const Formattable& number, number::impl::DecimalQuantity& output,
                                  UErrorCode& status) const;
+
 #endif
 
     /**
@@ -1995,6 +1969,58 @@ public:
      */
     virtual UClassID getDynamicClassID(void) const U_OVERRIDE;
 
+  private:
+
+    /** Rebuilds the formatter object from the property bag. */
+    void refreshFormatter(UErrorCode& status);
+
+    /**
+     * Updates the property bag with settings from the given pattern.
+     *
+     * @param pattern The pattern string to parse.
+     * @param ignoreRounding Whether to leave out rounding information (minFrac, maxFrac, and rounding
+     *     increment) when parsing the pattern. This may be desirable if a custom rounding mode, such
+     *     as CurrencyUsage, is to be used instead. One of {@link
+     *     PatternStringParser#IGNORE_ROUNDING_ALWAYS}, {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY},
+     *     or {@link PatternStringParser#IGNORE_ROUNDING_NEVER}.
+     * @see PatternAndPropertyUtils#parseToExistingProperties
+     */
+    void setPropertiesFromPattern(const UnicodeString& pattern, int32_t ignoreRounding,
+                                  UErrorCode& status);
+
+    //=====================================================================================//
+    //                                   INSTANCE FIELDS                                   //
+    //=====================================================================================//
+
+    /**
+     * The property bag corresponding to user-specified settings and settings from the pattern string.
+     * In principle this should be final, but serialize and clone won't work if it is final. Does not
+     * need to be volatile because the reference never changes.
+     */
+    number::impl::DecimalFormatProperties* properties;
+
+    /**
+     * The symbols for the current locale. Volatile because threads may read and write at the same
+     * time.
+     */
+    const DecimalFormatSymbols* symbols;
+
+    /**
+     * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
+     * #format} method uses the formatter directly without needing to synchronize. Volatile because
+     * threads may read and write at the same time.
+     */
+    number::LocalizedNumberFormatter* formatter;
+
+    /**
+     * The effective properties as exported from the formatter object. Volatile because threads may
+     * read and write at the same time.
+     */
+    number::impl::DecimalFormatProperties* exportedProperties;
+
+    const numparse::impl::NumberParserImpl* parser;
+    const numparse::impl::NumberParserImpl* parserWithCurrency;
+
 };
 
 U_NAMESPACE_END
index 878b6089a07ef63cbe79e474946eb4616523215e..89fd71fe9a9f7b5924965fdbb1db50798cbf7a53 100644 (file)
@@ -1892,6 +1892,13 @@ class U_I18N_API NumberFormatterSettings {
      */
     Derived threshold(int32_t threshold) const;
 
+    /**
+     * Internal fluent setter to overwrite the entire macros object.
+     *
+     * @internal ICU 60: This API is ICU internal only.
+     */
+    Derived macros(impl::MacroProps& macros) const;
+
 #endif  /* U_HIDE_INTERNAL_API */
 
     /**
index d44d6f21f3affe623e12cccf482698c75c7a0c34..881232918c06fd40689bfafd49c6c6d739db533b 100644 (file)
@@ -5,7 +5,6 @@ package com.ibm.icu.number;
 import java.util.Locale;
 
 import com.ibm.icu.impl.number.DecimalFormatProperties;
-import com.ibm.icu.impl.number.MacroProps;
 import com.ibm.icu.text.DecimalFormatSymbols;
 import com.ibm.icu.util.ULocale;
 
@@ -469,6 +468,9 @@ public final class NumberFormatter {
     }
 
     /**
+     * Note: In Java, since NumberPropertyMapper is package-private, this method is here so that it is
+     * accessible to tests.
+     *
      * @internal
      * @deprecated ICU 60 This API is ICU internal only.
      */
@@ -477,7 +479,6 @@ public final class NumberFormatter {
             DecimalFormatProperties properties,
             DecimalFormatSymbols symbols,
             DecimalFormatProperties exportedProperties) {
-        MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, exportedProperties);
-        return NumberFormatter.with().macros(macros);
+        return NumberPropertyMapper.create(properties, symbols, exportedProperties);
     }
 }
index c7a1a664ff49c2f8d8d9379ea40de85dac60b7b7..168b43989cec62f71c123efe541bcc22cd82287a 100644 (file)
@@ -42,6 +42,15 @@ final class NumberPropertyMapper {
         return NumberFormatter.with().macros(macros);
     }
 
+    /** Convenience method to create a NumberFormatter directly from Properties. */
+    public static UnlocalizedNumberFormatter create(
+            DecimalFormatProperties properties,
+            DecimalFormatSymbols symbols,
+            DecimalFormatProperties exportedProperties) {
+        MacroProps macros = oldToNew(properties, symbols, exportedProperties);
+        return NumberFormatter.with().macros(macros);
+    }
+
     /**
      * Convenience method to create a NumberFormatter directly from a pattern string. Something like this
      * could become public API if there is demand.