]> granicus.if.org Git - icu/commitdiff
ICU-13634 Number property mapper is building. Currently there is a linker error.
authorShane Carr <shane@unicode.org>
Thu, 15 Mar 2018 07:46:56 +0000 (07:46 +0000)
committerShane Carr <shane@unicode.org>
Thu, 15 Mar 2018 07:46:56 +0000 (07:46 +0000)
X-SVN-Rev: 41107

12 files changed:
icu4c/source/i18n/number_grouping.cpp
icu4c/source/i18n/number_mapper.cpp
icu4c/source/i18n/number_mapper.h
icu4c/source/i18n/number_notation.cpp
icu4c/source/i18n/number_padding.cpp
icu4c/source/i18n/number_patternstring.cpp
icu4c/source/i18n/number_patternstring.h
icu4c/source/i18n/number_types.h
icu4c/source/i18n/unicode/compactdecimalformat.h
icu4c/source/i18n/unicode/decimfmt.h
icu4j/main/classes/core/src/com/ibm/icu/impl/number/Padder.java
icu4j/main/classes/core/src/com/ibm/icu/number/NumberPropertyMapper.java

index 1f4a163d7bf45bdc26f7088d55b840df28e949fb..a77e505a2213be506bdc3b7819dd868a8253554f 100644 (file)
@@ -51,6 +51,15 @@ Grouper Grouper::forStrategy(UGroupingStrategy grouping) {
     }
 }
 
+Grouper Grouper::forProperties(const DecimalFormatProperties& properties) {
+    auto grouping1 = static_cast<int16_t>(properties.groupingSize);
+    auto grouping2 = static_cast<int16_t>(properties.secondaryGroupingSize);
+    auto minGrouping = static_cast<int16_t>(properties.minimumGroupingDigits);
+    grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : grouping1;
+    grouping2 = grouping2 > 0 ? grouping2 : grouping1;
+    return {grouping1, grouping2, minGrouping};
+}
+
 void Grouper::setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Locale& locale) {
     if (fGrouping1 != -2 && fGrouping2 != -4) {
         return;
index b1e596671dd1b7586b7c73e017c68ea54037b4c1..949f88aadd24ff1707e344929325ab36586cbbcd 100644 (file)
@@ -10,6 +10,7 @@
 #define UNISTR_FROM_STRING_EXPLICIT
 
 #include "number_mapper.h"
+#include "number_patternstring.h"
 
 using namespace icu;
 using namespace icu::number;
@@ -18,13 +19,306 @@ using namespace icu::number::impl;
 
 UnlocalizedNumberFormatter NumberPropertyMapper::create(const DecimalFormatProperties& properties,
                                                         const DecimalFormatSymbols& symbols,
+                                                        DecimalFormatWarehouse& warehouse,
+                                                        UErrorCode& status) {
+    return NumberFormatter::with().macros(oldToNew(properties, symbols, warehouse, nullptr, status));
+}
+
+UnlocalizedNumberFormatter NumberPropertyMapper::create(const DecimalFormatProperties& properties,
+                                                        const DecimalFormatSymbols& symbols,
+                                                        DecimalFormatWarehouse& warehouse,
                                                         DecimalFormatProperties& exportedProperties,
                                                         UErrorCode& status) {
+    return NumberFormatter::with().macros(
+            oldToNew(
+                    properties, symbols, warehouse, &exportedProperties, status));
+}
+
+MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& properties,
+                                          const DecimalFormatSymbols& symbols,
+                                          DecimalFormatWarehouse& warehouse,
+                                          DecimalFormatProperties* exportedProperties,
+                                          UErrorCode& status) {
+    MacroProps macros;
+    Locale locale = symbols.getLocale();
+
+    /////////////
+    // SYMBOLS //
+    /////////////
+
+    macros.symbols.setTo(symbols);
+
+    //////////////////
+    // PLURAL RULES //
+    //////////////////
+
+    // TODO
+
+    /////////////
+    // AFFIXES //
+    /////////////
+
+    AffixPatternProvider* affixProvider;
+    if (properties.currencyPluralInfo.fPtr.isNull()) {
+        warehouse.currencyPluralInfoAPP.setToBogus();
+        warehouse.propertiesAPP.setTo(properties);
+        affixProvider = &warehouse.propertiesAPP;
+    } else {
+        warehouse.currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr);
+        warehouse.propertiesAPP.setToBogus();
+        affixProvider = &warehouse.currencyPluralInfoAPP;
+    }
+    macros.affixProvider = affixProvider;
+
+    ///////////
+    // UNITS //
+    ///////////
+
+    bool useCurrency = (
+            !properties.currency.isNull() || !properties.currencyPluralInfo.fPtr.isNull() ||
+            !properties.currencyUsage.isNull() || affixProvider->hasCurrencySign());
+    // TODO: CustomSymbolCurrency
+    CurrencyUnit currency = {u"USD", status};
+    UCurrencyUsage currencyUsage = properties.currencyUsage.getOrDefault(UCURR_USAGE_STANDARD);
+    if (useCurrency) {
+        // NOTE: Slicing is OK.
+        macros.unit = currency; // NOLINT
+    }
+
+    ///////////////////////
+    // ROUNDING STRATEGY //
+    ///////////////////////
+
+    int32_t maxInt = properties.maximumIntegerDigits;
+    int32_t minInt = properties.minimumIntegerDigits;
+    int32_t maxFrac = properties.maximumFractionDigits;
+    int32_t minFrac = properties.minimumFractionDigits;
+    int32_t minSig = properties.minimumSignificantDigits;
+    int32_t maxSig = properties.maximumSignificantDigits;
+    double roundingIncrement = properties.roundingIncrement;
+    RoundingMode roundingMode = properties.roundingMode.getOrDefault(UNUM_ROUND_HALFEVEN);
+    bool explicitMinMaxFrac = minFrac != -1 || maxFrac != -1;
+    bool explicitMinMaxSig = minSig != -1 || maxSig != -1;
+    // Resolve min/max frac for currencies, required for the validation logic and for when minFrac or
+    // maxFrac was
+    // set (but not both) on a currency instance.
+    // NOTE: Increments are handled in "Rounder.constructCurrency()".
+    if (useCurrency && (minFrac == -1 || maxFrac == -1)) {
+        int32_t digits = ucurr_getDefaultFractionDigitsForUsage(
+                currency.getISOCurrency(), currencyUsage, &status);
+        if (minFrac == -1 && maxFrac == -1) {
+            minFrac = digits;
+            maxFrac = digits;
+        } else if (minFrac == -1) {
+            minFrac = std::min(maxFrac, digits);
+        } else /* if (maxFrac == -1) */ {
+            maxFrac = std::max(minFrac, digits);
+        }
+    }
+    // Validate min/max int/frac.
+    // For backwards compatibility, minimum overrides maximum if the two conflict.
+    // The following logic ensures that there is always a minimum of at least one digit.
+    if (minInt == 0 && maxFrac != 0) {
+        // Force a digit after the decimal point.
+        minFrac = minFrac <= 0 ? 1 : minFrac;
+        maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac;
+        minInt = 0;
+        maxInt = maxInt < 0 ? -1 : maxInt > kMaxIntFracSig ? -1 : maxInt;
+    } else {
+        // Force a digit before the decimal point.
+        minFrac = minFrac < 0 ? 0 : minFrac;
+        maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac;
+        minInt = minInt <= 0 ? 1 : minInt > kMaxIntFracSig ? 1 : minInt;
+        maxInt = maxInt < 0 ? -1 : maxInt < minInt ? minInt : maxInt > kMaxIntFracSig ? -1 : maxInt;
+    }
+    Rounder rounding;
+    if (!properties.currencyUsage.isNull()) {
+        rounding = Rounder::constructCurrency(currencyUsage).withCurrency(currency);
+    } else if (roundingIncrement != 0.0) {
+        rounding = Rounder::constructIncrement(roundingIncrement, minFrac);
+    } else if (explicitMinMaxSig) {
+        minSig = minSig < 1 ? 1 : minSig > kMaxIntFracSig ? kMaxIntFracSig : minSig;
+        maxSig = maxSig < 0 ? kMaxIntFracSig : maxSig < minSig ? minSig : maxSig > kMaxIntFracSig
+                                                                          ? kMaxIntFracSig : maxSig;
+        rounding = Rounder::constructSignificant(minSig, maxSig);
+    } else if (explicitMinMaxFrac) {
+        rounding = Rounder::constructFraction(minFrac, maxFrac);
+    } else if (useCurrency) {
+        rounding = Rounder::constructCurrency(currencyUsage);
+    }
+    if (!rounding.isBogus()) {
+        rounding = rounding.withMode(roundingMode);
+        macros.rounder = rounding;
+    }
+
+    ///////////////////
+    // INTEGER WIDTH //
+    ///////////////////
+
+    macros.integerWidth = IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt);
+
+    ///////////////////////
+    // GROUPING STRATEGY //
+    ///////////////////////
+
+    macros.grouper = Grouper::forProperties(properties);
+
+    /////////////
+    // PADDING //
+    /////////////
+
+    if (properties.formatWidth != -1) {
+        macros.padder = Padder::forProperties(properties);
+    }
+
+    ///////////////////////////////
+    // DECIMAL MARK ALWAYS SHOWN //
+    ///////////////////////////////
+
+    macros.decimal = properties.decimalSeparatorAlwaysShown ? UNUM_DECIMAL_SEPARATOR_ALWAYS
+                                                            : UNUM_DECIMAL_SEPARATOR_AUTO;
+
+    ///////////////////////
+    // SIGN ALWAYS SHOWN //
+    ///////////////////////
+
+    macros.sign = properties.signAlwaysShown ? UNUM_SIGN_ALWAYS : UNUM_SIGN_AUTO;
+
+    /////////////////////////
+    // SCIENTIFIC NOTATION //
+    /////////////////////////
+
+    if (properties.minimumExponentDigits != -1) {
+        // Scientific notation is required.
+        // This whole section feels like a hack, but it is needed for regression tests.
+        // The mapping from property bag to scientific notation is nontrivial due to LDML rules.
+        if (maxInt > 8) {
+            // But #13110: The maximum of 8 digits has unknown origins and is not in the spec.
+            // If maxInt is greater than 8, it is set to minInt, even if minInt is greater than 8.
+            maxInt = minInt;
+            macros.integerWidth = IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt);
+        } else if (maxInt > minInt && minInt > 1) {
+            // Bug #13289: if maxInt > minInt > 1, then minInt should be 1.
+            minInt = 1;
+            macros.integerWidth = IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt);
+        }
+        int engineering = maxInt < 0 ? -1 : maxInt;
+        macros.notation = ScientificNotation(
+                // Engineering interval:
+                static_cast<int8_t>(engineering),
+                // Enforce minimum integer digits (for patterns like "000.00E0"):
+                (engineering == minInt),
+                // Minimum exponent digits:
+                static_cast<digits_t>(properties.minimumExponentDigits),
+                // Exponent sign always shown:
+                properties.exponentSignAlwaysShown ? UNUM_SIGN_ALWAYS : UNUM_SIGN_AUTO);
+        // Scientific notation also involves overriding the rounding mode.
+        // TODO: Overriding here is a bit of a hack. Should this logic go earlier?
+        if (macros.rounder.fType == Rounder::RounderType::RND_FRACTION) {
+            // For the purposes of rounding, get the original min/max int/frac, since the local
+            // variables
+            // have been manipulated for display purposes.
+            int minInt_ = properties.minimumIntegerDigits;
+            int minFrac_ = properties.minimumFractionDigits;
+            int maxFrac_ = properties.maximumFractionDigits;
+            if (minInt_ == 0 && maxFrac_ == 0) {
+                // Patterns like "#E0" and "##E0", which mean no rounding!
+                macros.rounder = Rounder::unlimited().withMode(roundingMode);
+            } else if (minInt_ == 0 && minFrac_ == 0) {
+                // Patterns like "#.##E0" (no zeros in the mantissa), which mean round to maxFrac+1
+                macros.rounder = Rounder::constructSignificant(1, maxFrac_ + 1).withMode(roundingMode);
+            } else {
+                // All other scientific patterns, which mean round to minInt+maxFrac
+                macros.rounder = Rounder::constructSignificant(minInt_ + minFrac_, minInt_ + maxFrac_)
+                        .withMode(roundingMode);
+            }
+        }
+    }
+
+    //////////////////////
+    // COMPACT NOTATION //
+    //////////////////////
+
+    if (!properties.compactStyle.isNull()) {
+        if (properties.compactStyle.getNoError() == UNumberCompactStyle::UNUM_LONG) {
+            macros.notation = Notation::compactLong();
+        } else {
+            macros.notation = Notation::compactShort();
+        }
+        // Do not forward the affix provider.
+        macros.affixProvider = nullptr;
+    }
+
+    /////////////////
+    // MULTIPLIERS //
+    /////////////////
+
+    if (properties.magnitudeMultiplier != 0) {
+        macros.multiplier = MultiplierImpl::magnitude(properties.magnitudeMultiplier);
+    } else if (properties.multiplier != 1) {
+        macros.multiplier = MultiplierImpl::integer(properties.multiplier);
+    }
+
+    //////////////////////
+    // PROPERTY EXPORTS //
+    //////////////////////
+
+    if (exportedProperties != nullptr) {
+
+        exportedProperties->roundingMode = roundingMode;
+        exportedProperties->minimumIntegerDigits = minInt;
+        exportedProperties->maximumIntegerDigits = maxInt == -1 ? INT32_MAX : maxInt;
+
+        Rounder rounding_;
+        if (rounding.fType == Rounder::RounderType::RND_CURRENCY) {
+            rounding_ = rounding.withCurrency(currency, status);
+        } else {
+            rounding_ = rounding;
+        }
+        int minFrac_ = minFrac;
+        int maxFrac_ = maxFrac;
+        int minSig_ = minSig;
+        int maxSig_ = maxSig;
+        double increment_ = 0.0;
+        if (rounding_.fType == Rounder::RounderType::RND_FRACTION) {
+            minFrac_ = rounding_.fUnion.fracSig.fMinFrac;
+            maxFrac_ = rounding_.fUnion.fracSig.fMaxFrac;
+        } else if (rounding_.fType == Rounder::RounderType::RND_INCREMENT) {
+            increment_ = rounding_.fUnion.increment.fIncrement;
+            minFrac_ = rounding_.fUnion.increment.fMinFrac;
+            maxFrac_ = rounding_.fUnion.increment.fMinFrac;
+        } else if (rounding_.fType == Rounder::RounderType::RND_SIGNIFICANT) {
+            minSig_ = rounding_.fUnion.fracSig.fMinSig;
+            maxSig_ = rounding_.fUnion.fracSig.fMaxSig;
+        }
+
+        exportedProperties->minimumFractionDigits = minFrac_;
+        exportedProperties->maximumFractionDigits = maxFrac_;
+        exportedProperties->minimumSignificantDigits = minSig_;
+        exportedProperties->maximumSignificantDigits = maxSig_;
+        exportedProperties->roundingIncrement = increment_;
+    }
+
+    return macros;
+}
+
+
+void PropertiesAffixPatternProvider::setTo(const DecimalFormatProperties& properties) {
+    // TODO
+}
+
+bool PropertiesAffixPatternProvider::hasBody() const {
+    return true;
+}
+
+
+void CurrencyPluralInfoAffixProvider::setTo(const CurrencyPluralInfo& cpi) {
     // TODO
-    status = U_UNSUPPORTED_ERROR;
-    return NumberFormatter::with();
 }
 
+bool CurrencyPluralInfoAffixProvider::hasBody() const {
+    return affixesByPlural[StandardPlural::OTHER].hasBody();
+}
 
 
 #endif /* #if !UCONFIG_NO_FORMATTING */
index c3960a665be472ab7566710c0968c410caa69ba5..842b183fd535164440fe035be7ba8ab9040e2f19 100644 (file)
@@ -8,11 +8,96 @@
 #define __NUMBER_MAPPER_H__
 
 #include "number_types.h"
+#include "unicode/currpinf.h"
+#include "standardplural.h"
+#include "number_patternstring.h"
 
 U_NAMESPACE_BEGIN namespace number {
 namespace impl {
 
 
+class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemory {
+  public:
+    bool isBogus() const;
+
+    void setTo(const DecimalFormatProperties& properties);
+
+    void setToBogus();
+
+    // AffixPatternProvider Methods:
+
+    char16_t charAt(int flags, int i) const U_OVERRIDE;
+
+    int length(int flags) const U_OVERRIDE;
+
+    UnicodeString getString(int flags) const U_OVERRIDE;
+
+    bool hasCurrencySign() const U_OVERRIDE;
+
+    bool positiveHasPlusSign() const U_OVERRIDE;
+
+    bool hasNegativeSubpattern() const U_OVERRIDE;
+
+    bool negativeHasMinusSign() const U_OVERRIDE;
+
+    bool containsSymbolType(AffixPatternType, UErrorCode&) const U_OVERRIDE;
+
+    virtual bool hasBody() const U_OVERRIDE;
+
+  private:
+    UnicodeString posPrefix;
+    UnicodeString posSuffix;
+    UnicodeString negPrefix;
+    UnicodeString negSuffix;
+
+    bool fBogus{true};
+};
+
+
+class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMemory {
+  public:
+    bool isBogus() const;
+
+    void setTo(const CurrencyPluralInfo& cpi);
+
+    void setToBogus();
+
+    // AffixPatternProvider Methods:
+
+    char16_t charAt(int flags, int i) const U_OVERRIDE;
+
+    int length(int flags) const U_OVERRIDE;
+
+    UnicodeString getString(int flags) const U_OVERRIDE;
+
+    bool hasCurrencySign() const U_OVERRIDE;
+
+    bool positiveHasPlusSign() const U_OVERRIDE;
+
+    bool hasNegativeSubpattern() const U_OVERRIDE;
+
+    bool negativeHasMinusSign() const U_OVERRIDE;
+
+    bool containsSymbolType(AffixPatternType, UErrorCode&) const U_OVERRIDE;
+
+    virtual bool hasBody() const U_OVERRIDE;
+
+  private:
+    ParsedPatternInfo affixesByPlural[StandardPlural::COUNT];
+
+    bool fBogus{true};
+};
+
+
+/**
+ * A struct for ownership of a few objects needed for formatting.
+ */
+struct DecimalFormatWarehouse {
+    PropertiesAffixPatternProvider propertiesAPP;
+    CurrencyPluralInfoAffixProvider currencyPluralInfoAPP;
+};
+
+
 /**
  * Utilities for converting between a DecimalFormatProperties and a MacroProps.
  */
@@ -20,21 +105,16 @@ class NumberPropertyMapper {
   public:
     /** Convenience method to create a NumberFormatter directly from Properties. */
     static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
-                                             const DecimalFormatSymbols& symbols, UErrorCode& status);
+                                             const DecimalFormatSymbols& symbols,
+                                             DecimalFormatWarehouse& warehouse, UErrorCode& status);
 
     /** Convenience method to create a NumberFormatter directly from Properties. */
     static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
                                              const DecimalFormatSymbols& symbols,
+                                             DecimalFormatWarehouse& warehouse,
                                              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
@@ -49,9 +129,9 @@ class NumberPropertyMapper {
      *            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);
+    static MacroProps oldToNew(const DecimalFormatProperties& properties,
+                               const DecimalFormatSymbols& symbols, DecimalFormatWarehouse& warehouse,
+                               DecimalFormatProperties* exportedProperties, UErrorCode& status);
 };
 
 
index f4ad333354d0c7ee48b10fa91c4357c871a6e390..da61433b1c295dcb552a12a96b37b311fe364236 100644 (file)
@@ -36,6 +36,19 @@ ScientificNotation Notation::engineering() {
     return {NTN_SCIENTIFIC, union_};
 }
 
+ScientificNotation::ScientificNotation(int8_t fEngineeringInterval, bool fRequireMinInt,
+                                       impl::digits_t fMinExponentDigits,
+                                       UNumberSignDisplay fExponentSignDisplay) {
+    ScientificSettings settings;
+    settings.fEngineeringInterval = fEngineeringInterval;
+    settings.fRequireMinInt = fRequireMinInt;
+    settings.fMinExponentDigits = fMinExponentDigits;
+    settings.fExponentSignDisplay = fExponentSignDisplay;
+    NotationUnion union_;
+    union_.scientific = settings;
+    *this = {NTN_SCIENTIFIC, union_};
+}
+
 Notation Notation::compactShort() {
     NotationUnion union_;
     union_.compactStyle = CompactStyle::UNUM_SHORT;
index b1db3490cd4489f3f9371d08ef784006c879d698..3c470df50457333b47f22f54fc0dbd263a02e5ae 100644 (file)
@@ -8,6 +8,7 @@
 #include "unicode/numberformatter.h"
 #include "number_types.h"
 #include "number_stringbuilder.h"
+#include "number_decimfmtprops.h"
 
 using namespace icu;
 using namespace icu::number;
@@ -15,6 +16,8 @@ using namespace icu::number::impl;
 
 namespace {
 
+static UChar32 kFallbackPadChar = 0x0020;
+
 int32_t
 addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, NumberStringBuilder &string, int32_t index,
                  UErrorCode &status) {
@@ -47,6 +50,16 @@ Padder Padder::codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosit
     }
 }
 
+Padder Padder::forProperties(const DecimalFormatProperties& properties) {
+    UChar32 padCp;
+    if (properties.padString.length() > 0) {
+        padCp = properties.padString.char32At(0);
+    } else {
+        padCp = kFallbackPadChar;
+    }
+    return {padCp, properties.formatWidth, properties.padPosition.getOrDefault(UNUM_PAD_BEFORE_PREFIX)};
+}
+
 int32_t Padder::padAndApply(const Modifier &mod1, const Modifier &mod2,
                             NumberStringBuilder &string, int32_t leftIndex, int32_t rightIndex,
                             UErrorCode &status) const {
index 7bdd6fb71dd009f22605bbe9a6ad8ea316dfd788..7ec0297c6ececa85a951041219a39695539be3cc 100644 (file)
@@ -32,6 +32,11 @@ PatternParser::parseToProperties(const UnicodeString& pattern, IgnoreRounding ig
     return properties;
 }
 
+DecimalFormatProperties PatternParser::parseToProperties(const UnicodeString& pattern,
+                                                         UErrorCode& status) {
+    return parseToProperties(pattern, IGNORE_ROUNDING_NEVER, status);
+}
+
 void
 PatternParser::parseToExistingProperties(const UnicodeString& pattern, DecimalFormatProperties& properties,
                                          IgnoreRounding ignoreRounding, UErrorCode& status) {
index d0e62ef21f45517d16e48c46f91ff2223ca00af6..742ee3547cd5b82980c915be5dba903cae2aba46 100644 (file)
@@ -177,6 +177,8 @@ class U_I18N_API PatternParser {
     static DecimalFormatProperties parseToProperties(const UnicodeString& pattern,
                                                      IgnoreRounding ignoreRounding, UErrorCode& status);
 
+    static DecimalFormatProperties parseToProperties(const UnicodeString& pattern, UErrorCode& status);
+
     /**
      * Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string
      * will be overwritten with either their default value or with the value coming from the pattern string. Properties
index 35a94bcdedf2da2b136739ee5f7b6739de8330cf..ac0188f49824492956a514b82d772aaebc2367fb 100644 (file)
@@ -305,6 +305,10 @@ class U_I18N_API NullableValue {
         return fValue;
     }
 
+    T getOrDefault(T defaultValue) const {
+        return fNull ? defaultValue : fValue;
+    }
+
   private:
     bool fNull;
     T fValue;
index f5911176c8d1015e4d3e4f86f3526ce933bcf033..e5d27de05a6a968a47c787b88648d94bcc878b44 100644 (file)
@@ -112,7 +112,7 @@ public:
      *                  other classes have different class IDs.
      * @stable ICU 51
      */
-    virtual UClassID getDynamicClassID() const;
+    virtual UClassID getDynamicClassID() const U_OVERRIDE;
 };
 
 U_NAMESPACE_END
index 443aa1a532e611c643d9cd2ebd16a4ca74519b20..88d50c7a8916c89267b340a83c929a7dbe1109ca 100644 (file)
@@ -42,7 +42,6 @@
 #include "unicode/stringpiece.h"
 #include "unicode/curramt.h"
 #include "unicode/enumset.h"
-#include "unicode/numberformatter.h"
 
 #ifndef U_HIDE_INTERNAL_API
 /**
@@ -68,9 +67,11 @@ class PluralRules;
 class VisibleDigitsWithExponent;
 
 namespace number {
+class LocalizedNumberFormatter;
 namespace impl {
 class DecimalQuantity;
 struct DecimalFormatProperties;
+struct DecimalFormatWarehouse;
 }
 }
 
@@ -1948,7 +1949,7 @@ class U_I18N_API DecimalFormat : public NumberFormat {
      * @return An instance of LocalizedNumberFormatter with the same behavior as this DecimalFormat.
      * @draft ICU 62
      */
-    number::LocalizedNumberFormatter toNumberFormatter() const;
+    const number::LocalizedNumberFormatter& toNumberFormatter() const;
 
     /**
      * Return the class ID for this class.  This is useful only for
@@ -2023,6 +2024,9 @@ class U_I18N_API DecimalFormat : public NumberFormat {
      */
     LocalPointer<number::impl::DecimalFormatProperties> fExportedProperties;
 
+    /** A field for a few additional helper object that need ownership. */
+    LocalPointer<number::impl::DecimalFormatWarehouse> fWarehouse;
+
     LocalPointer<const numparse::impl::NumberParserImpl> fParser;
     LocalPointer<const numparse::impl::NumberParserImpl> fParserWithCurrency;
 
index efb4cec0951f1ab80bdffa3b08e00307fff1ab99..97a310900dac47b0ff6afc55b8212dd3e77958b0 100644 (file)
@@ -66,6 +66,12 @@ public class Padder {
         }
     }
 
+    public static Padder forProperties(DecimalFormatProperties properties) {
+        return new Padder(properties.getPadString(),
+                properties.getFormatWidth(),
+                properties.getPadPosition());
+    }
+
     public boolean isValid() {
         return targetWidth > 0;
     }
index 168b43989cec62f71c123efe541bcc22cd82287a..0d33059eda4435de442f6d36ed8efb18ea99da3c 100644 (file)
@@ -54,6 +54,8 @@ final class NumberPropertyMapper {
     /**
      * Convenience method to create a NumberFormatter directly from a pattern string. Something like this
      * could become public API if there is demand.
+     *
+     * NOTE: This appears to be dead code.
      */
     public static UnlocalizedNumberFormatter create(String pattern, DecimalFormatSymbols symbols) {
         DecimalFormatProperties properties = PatternStringParser.parseToProperties(pattern);
@@ -159,13 +161,13 @@ final class NumberPropertyMapper {
         if (minInt == 0 && maxFrac != 0) {
             // Force a digit after the decimal point.
             minFrac = minFrac <= 0 ? 1 : minFrac;
-            maxFrac = maxFrac < 0 ? Integer.MAX_VALUE : maxFrac < minFrac ? minFrac : maxFrac;
+            maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac;
             minInt = 0;
             maxInt = maxInt < 0 ? -1 : maxInt > RoundingUtils.MAX_INT_FRAC_SIG ? -1 : maxInt;
         } else {
             // Force a digit before the decimal point.
             minFrac = minFrac < 0 ? 0 : minFrac;
-            maxFrac = maxFrac < 0 ? Integer.MAX_VALUE : maxFrac < minFrac ? minFrac : maxFrac;
+            maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac;
             minInt = minInt <= 0 ? 1 : minInt > RoundingUtils.MAX_INT_FRAC_SIG ? 1 : minInt;
             maxInt = maxInt < 0 ? -1
                     : maxInt < minInt ? minInt : maxInt > RoundingUtils.MAX_INT_FRAC_SIG ? -1 : maxInt;
@@ -210,9 +212,7 @@ final class NumberPropertyMapper {
         /////////////
 
         if (properties.getFormatWidth() != -1) {
-            macros.padder = new Padder(properties.getPadString(),
-                    properties.getFormatWidth(),
-                    properties.getPadPosition());
+            macros.padder = Padder.forProperties(properties);
         }
 
         ///////////////////////////////