]> granicus.if.org Git - icu/commitdiff
ICU-13177 Pointing DecimalFormat.java and CompactDecimalFormat.java at the new API...
authorShane Carr <shane@unicode.org>
Fri, 4 Aug 2017 22:43:34 +0000 (22:43 +0000)
committerShane Carr <shane@unicode.org>
Fri, 4 Aug 2017 22:43:34 +0000 (22:43 +0000)
X-SVN-Rev: 40313

24 files changed:
icu4c/source/test/testdata/numberformattestspecification.txt
icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantityBCD.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternString.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/Properties.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/CompactDecimalFormat.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/SimpleModifier.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/rounders/SignificantDigitsRounder.java
icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java
icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberformattestspecification.txt
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/IntlTestDecimalFormatAPI.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/IntlTestDecimalFormatAPIC.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/IntlTestDecimalFormatSymbolsC.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/MeasureUnitTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatDataDrivenTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatRegressionTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTestCases.txt
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberRegressionTests.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PropertiesTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/RounderTest.java [deleted file]

index 5200bc83d6f70cba33811490936351c05690f18c..005158e024e84850a1f157900c7ef5c8c1683cd8 100644 (file)
@@ -259,8 +259,8 @@ $**####,##0 1234    $***1\u00a0234  K
 // In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
 \u00a4\u00a4 **####0.00        433.0   EUR *433,00     JK
 // In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
-// S fails this one because the test code bypasses CurrencyUsage
-\u00a4\u00a4 **#######0        433.0   EUR *433,00     JKS
+// S and Q fail this one because the test code bypasses CurrencyUsage
+\u00a4\u00a4 **#######0        433.0   EUR *433,00     JKSQ
 
 test padding and currencies
 begin
@@ -338,8 +338,8 @@ minIntegerDigits    maxIntegerDigits        minFractionDigits       maxFractionDigits       output  bre
 // JDK gives E0 instead of allowing for unlimited precision
 // S obeys the maximum integer digits and returns .299792458E9
 0      0       0       0       2.99792458E8    KS
-// JDK and S give .299792E9
-0      1       0       5       2.9979E8        KS
+// JDK and S give .299792E9; Q gives 2.99792E8
+0      1       0       5       2.9979E8        KSQ
 // JDK gives 300E6     
 0      3       0       0       299.792458E6    K
 // JDK gives 299.8E6 (maybe maxInt + maxFrac instead of minInt + maxFrac)?
@@ -356,12 +356,13 @@ minIntegerDigits  maxIntegerDigits        minFractionDigits       maxFractionDigits       output  bre
 // JDK gives E0
 // S obeys the maximum integer digits
 0      0       1       0       2.99792458E8    KS
-// JDK gives .2998E9
-0      0       0       4       2.998E8 KS
+// JDK and S give .2998E9
+0      0       0       4       2.998E8 KSQ
 // S correctly formats this as 29.979246E7.
 // JDK uses 8 + 6 for significant digits instead of 2 + 6
 // J and C return 2.9979246E8.
-2      8       1       6       29.979246E7     CJK
+// TODO: Merge trunk
+2      8       1       6       29.979246E7     CJKQ
 // Treat max int digits > 8 as being the same as min int digits.
 // This behavior is not spelled out in the specification.
 // JDK fails here because it tries to use 9 + 6 = 15 sig digits.
@@ -405,12 +406,12 @@ begin
 format maxIntegerDigits        output  breaks
 123    1       3       
 0      0       0
-// S ignores max integer if it is less than zero and prints "123"
-123    -2147483648     0       S
+// S and Q ignore max integer if it is less than zero and prints "123"
+123    -2147483648     0       SQ
 12345  1       5       
-12345  -2147483648     0       S
+12345  -2147483648     0       SQ
 5.3    1       5.3     
-5.3    -2147483648     .3      S
+5.3    -2147483648     .3      SQ
 
 test patterns with zero
 set locale en
@@ -489,8 +490,9 @@ output      grouping        breaks  grouping2       minGroupingDigits
 1,2345,6789    4
 1,23,45,6789   4       K       2
 1,23,45,6789   4       K       2       2
+// Q only supports minGrouping<=2
 123,456789     6               6       3
-123456789      6       JK      6       4
+123456789      6       JKQ     6       4
 
 test multiplier setters
 set locale en_US
@@ -498,8 +500,10 @@ begin
 format multiplier      output  breaks
 23     -12     -276
 23     -1      -23
-// ICU4J and JDK throw exception on zero multiplier. ICU4C does not.
-23     0       23      JKS
+// ICU4J and JDK throw exception on zero multiplier.
+// ICU4C and S print 23.
+// Q multiplies by zero and prints 0.
+23     0       0       CJKS
 23     1       23
 23     12      276
 -23    12      -276
@@ -513,8 +517,9 @@ begin
 format output  breaks
 -0.35  -0.25   K
 0.35   0.25    K
-0.39   0.5     K
-0.62   0.5     K
+// Q doesn't support mixing minFrac with roundingIncrement (prints 0.50).
+0.39   0.5     KQ
+0.62   0.5     KQ
 0.63   0.75    K
 
 test padding setters
@@ -539,20 +544,19 @@ output    breaks  useScientific
 
 test rounding mode setters
 set locale en_US
-set pattern 0.#
-set roundingIncrement 0.5
+set pattern 0.5
 begin
 format roundingMode    output  breaks
-1.24   halfUp  1       K
+1.24   halfUp  1.0     K
 1.25   halfUp  1.5     K
-1.25   halfDown        1       K
+1.25   halfDown        1.0     K
 1.26   halfDown        1.5     K
-1.25   halfEven        1       K
+1.25   halfEven        1.0     K
 -1.01  up      -1.5    K
--1.49  down    -1      K
+-1.49  down    -1.0    K
 1.01   up      1.5     K
-1.49   down    1       K
--1.01  ceiling -1
+1.49   down    1.0     K
+-1.01  ceiling -1.0
 -1.49  floor   -1.5
 
 test currency usage setters
@@ -584,7 +588,7 @@ set locale en
 set currency USD
 begin
 pattern        format  output  breaks
-#      123     123     S
+#      123     123     SQ
 // Currency rounding should always override the pattern.
 // K prints the currency in ISO format for some reason.
 \u00a4#        123     $123.00 K
@@ -659,7 +663,8 @@ begin
 format output  breaks
 Inf    [\u221e]
 -Inf   (\u221e)        K
-NaN    NaN     K
+// Q prints the affixes
+NaN    NaN     KQ
 
 test nan and infinity with multiplication
 set locale en
@@ -680,10 +685,11 @@ Inf       beforePrefix      $$$\u221e$    K
 Inf    afterPrefix     $$$  \u221e$    K
 Inf    beforeSuffix    $$$\u221e  $    K
 Inf    afterSuffix     $$$\u221e$      K
-NaN    beforePrefix        NaN K
-NaN    afterPrefix         NaN K
-NaN    beforeSuffix    NaN     K
-NaN    afterSuffix     NaN     K
+// Q gets $$$NaN$
+NaN    beforePrefix        NaN KQ
+NaN    afterPrefix         NaN KQ
+NaN    beforeSuffix    NaN     KQ
+NaN    afterSuffix     NaN     KQ
 
 test apply formerly localized patterns
 begin
@@ -1540,8 +1546,9 @@ set maxSigDigits 2
 begin
 format output  breaks
 // C and J get "1"
+// Q gets "1.0"
 // K gets "1.1" (??)
-0.975  0.98    CJK
+0.975  0.98    CJKQ
 
 test lenient parse currency match
 // This test is for #13112
index f1835d15f045a16f473e784d1f7deb6316464381..2a79cc56de04a2dcfec181a01f2e5cc27c10d40c 100644 (file)
@@ -222,6 +222,13 @@ public class AffixPatternUtils {
     return output.length() - startLength;
   }
 
+  /** Version of {@link #escape} that returns a String. */
+  public static String escape(CharSequence input) {
+    StringBuilder sb = new StringBuilder();
+    escape(input, sb);
+    return sb.toString();
+  }
+
   /**
    * Executes the unescape state machine. Replaces the unquoted characters "-", "+", "%", and "‰"
    * with their localized equivalents. Replaces "¤", "¤¤", and "¤¤¤" with the three argument
index c82775d9a485aad4ce1956430330026180ca12e4..0d6e82f87ac6c378f5cbac44ac56561fb89b54a2 100644 (file)
@@ -184,6 +184,9 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
 
   @Override
   public void multiplyBy(BigDecimal multiplicand) {
+    if (isInfinite() || isZero() || isNaN()) {
+      return;
+    }
     BigDecimal temp = toBigDecimal();
     temp = temp.multiply(multiplicand);
     setToBigDecimal(temp);
@@ -519,7 +522,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
    * @param n The value to consume.
    */
   @Override
-public void setToBigDecimal(BigDecimal n) {
+  public void setToBigDecimal(BigDecimal n) {
     setBcdToZero();
     flags = 0;
     if (n.signum() == -1) {
index 8cb1ced988a2d38421e0e1453b50098815899c3d..c05d7a110b67b25be209d42a123a74af6483955e 100644 (file)
@@ -46,6 +46,9 @@ public interface Modifier {
    * Gets the prefix string associated with this modifier, defined as the string that will be
    * inserted at leftIndex when {@link #apply} is called.
    *
+   * <p>TODO: Change this to appendPrefixTo(), or remove it entirely and do something different at
+   * the call sites.
+   *
    * @return The prefix string. Will not be null.
    */
   public String getPrefix();
@@ -54,6 +57,9 @@ public interface Modifier {
    * Gets the prefix string associated with this modifier, defined as the string that will be
    * inserted at rightIndex when {@link #apply} is called.
    *
+   * <p>TODO: Change this to appendPrefixTo(), or remove it entirely and do something different at
+   * the call sites.
+   *
    * @return The suffix string. Will not be null.
    */
   public String getSuffix();
@@ -102,8 +108,8 @@ public interface Modifier {
   /**
    * A starter implementation with defaults for some of the basic methods.
    *
-   * <p>Implements {@link PositiveNegativeModifier} only so that instances of this class can be used when
-   * a {@link PositiveNegativeModifier} is required.
+   * <p>Implements {@link PositiveNegativeModifier} only so that instances of this class can be used
+   * when a {@link PositiveNegativeModifier} is required.
    */
   public abstract static class BaseModifier extends Format.BeforeFormat
       implements Modifier, PositiveNegativeModifier {
index 375dbb279575a65450071a64265b1fef66a3f7c1..1a1b83b11982bdee1c1e3b56429de6004ddc59bf 100644 (file)
@@ -8,6 +8,8 @@ import com.ibm.icu.impl.number.formatters.PaddingFormat;
 import com.ibm.icu.impl.number.formatters.PaddingFormat.PadPosition;
 import com.ibm.icu.text.DecimalFormatSymbols;
 
+import newapi.impl.AffixPatternProvider;
+
 /**
  * Handles parsing and creation of the compact pattern string representation of a decimal format.
  */
@@ -507,7 +509,8 @@ public class PatternString {
       if (!ignoreRounding) {
         properties.setMinimumFractionDigits(minFrac);
         properties.setMaximumFractionDigits(positive.maximumFractionDigits);
-        properties.setRoundingIncrement(positive.rounding.toBigDecimal());
+        properties.setRoundingIncrement(
+            positive.rounding.toBigDecimal().setScale(positive.minimumFractionDigits));
       } else {
         properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
         properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
@@ -557,8 +560,8 @@ public class PatternString {
     }
 
     // Compute the affix patterns (required for both padding and affixes)
-    String posPrefix = ppr.getString(LdmlPatternInfo.PatternParseResult.POS_PREFIX);
-    String posSuffix = ppr.getString(LdmlPatternInfo.PatternParseResult.POS_SUFFIX);
+    String posPrefix = ppr.getString(AffixPatternProvider.Flags.PREFIX);
+    String posSuffix = ppr.getString(0);
 
     // Padding settings
     if (positive.paddingEndpoints != 0) {
@@ -568,7 +571,7 @@ public class PatternString {
               + AffixPatternUtils.unescapedLength(posPrefix)
               + AffixPatternUtils.unescapedLength(posSuffix);
       properties.setFormatWidth(paddingWidth);
-      String rawPaddingString = ppr.getString(LdmlPatternInfo.PatternParseResult.POS_PADDING);
+      String rawPaddingString = ppr.getString(AffixPatternProvider.Flags.PADDING);
       if (rawPaddingString.length() == 1) {
         properties.setPadString(rawPaddingString);
       } else if (rawPaddingString.length() == 2) {
@@ -594,8 +597,11 @@ public class PatternString {
     properties.setPositivePrefixPattern(posPrefix);
     properties.setPositiveSuffixPattern(posSuffix);
     if (negative != null) {
-      properties.setNegativePrefixPattern(ppr.getString(LdmlPatternInfo.PatternParseResult.NEG_PREFIX));
-      properties.setNegativeSuffixPattern(ppr.getString(LdmlPatternInfo.PatternParseResult.NEG_SUFFIX));
+      properties.setNegativePrefixPattern(
+          ppr.getString(
+              AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN | AffixPatternProvider.Flags.PREFIX));
+      properties.setNegativeSuffixPattern(
+          ppr.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN));
     } else {
       properties.setNegativePrefixPattern(null);
       properties.setNegativeSuffixPattern(null);
index 49d3b16fd55c76fa1b82cbb74c75616bf79ff97f..bb1092cb22a4faa0a4b660f149c4e9f301120b62 100644 (file)
@@ -32,7 +32,6 @@ import com.ibm.icu.impl.number.rounders.MagnitudeRounder;
 import com.ibm.icu.impl.number.rounders.SignificantDigitsRounder;
 import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
 import com.ibm.icu.text.CurrencyPluralInfo;
-import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
 import com.ibm.icu.text.MeasureFormat.FormatWidth;
 import com.ibm.icu.text.PluralRules;
 import com.ibm.icu.util.Currency;
@@ -121,7 +120,6 @@ public class Properties
   private transient RoundingMode roundingMode;
   private transient int secondaryGroupingSize;
   private transient boolean signAlwaysShown;
-  private transient SignificantDigitsMode significantDigitsMode;
 
   /*--------------------------------------------------------------------------------------------+/
   /| IMPORTANT!                                                                                 |/
@@ -182,7 +180,6 @@ public class Properties
     roundingMode = DEFAULT_ROUNDING_MODE;
     secondaryGroupingSize = DEFAULT_SECONDARY_GROUPING_SIZE;
     signAlwaysShown = DEFAULT_SIGN_ALWAYS_SHOWN;
-    significantDigitsMode = DEFAULT_SIGNIFICANT_DIGITS_MODE;
     return this;
   }
 
@@ -232,7 +229,6 @@ public class Properties
     roundingMode = other.roundingMode;
     secondaryGroupingSize = other.secondaryGroupingSize;
     signAlwaysShown = other.signAlwaysShown;
-    significantDigitsMode = other.significantDigitsMode;
     return this;
   }
 
@@ -283,7 +279,6 @@ public class Properties
     eq = eq && _equalsHelper(roundingMode, other.roundingMode);
     eq = eq && _equalsHelper(secondaryGroupingSize, other.secondaryGroupingSize);
     eq = eq && _equalsHelper(signAlwaysShown, other.signAlwaysShown);
-    eq = eq && _equalsHelper(significantDigitsMode, other.significantDigitsMode);
     return eq;
   }
 
@@ -348,7 +343,6 @@ public class Properties
     hashCode ^= _hashCodeHelper(roundingMode);
     hashCode ^= _hashCodeHelper(secondaryGroupingSize);
     hashCode ^= _hashCodeHelper(signAlwaysShown);
-    hashCode ^= _hashCodeHelper(significantDigitsMode);
     return hashCode;
   }
 
@@ -627,11 +621,6 @@ public class Properties
     return signAlwaysShown;
   }
 
-  @Override
-  public SignificantDigitsMode getSignificantDigitsMode() {
-    return significantDigitsMode;
-  }
-
   @Override
   public int hashCode() {
     return _hashCode();
@@ -960,12 +949,6 @@ public class Properties
     return this;
   }
 
-  @Override
-  public Properties setSignificantDigitsMode(SignificantDigitsMode significantDigitsMode) {
-    this.significantDigitsMode = significantDigitsMode;
-    return this;
-  }
-
   @Override
   public String toString() {
     StringBuilder result = new StringBuilder();
index 5a3931bcce026328de717b11a7cbf2882d394dfc..2caf40f20e0bea6953500168f67b1c1e8c3479ad 100644 (file)
@@ -24,7 +24,6 @@ import com.ibm.icu.impl.number.modifiers.PositiveNegativeAffixModifier;
 import com.ibm.icu.impl.number.rounders.SignificantDigitsRounder;
 import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
 import com.ibm.icu.text.CompactDecimalFormat.CompactType;
-import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
 import com.ibm.icu.text.DecimalFormatSymbols;
 import com.ibm.icu.text.NumberFormat;
 import com.ibm.icu.text.NumberingSystem;
@@ -104,8 +103,6 @@ public class CompactDecimalFormat extends Format.BeforeFormat {
 
   private static final int DEFAULT_MIN_SIG = 1;
   private static final int DEFAULT_MAX_SIG = 2;
-  private static final SignificantDigitsMode DEFAULT_SIG_MODE =
-      SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION;
 
   private static final ThreadLocal<Properties> threadLocalProperties =
       new ThreadLocal<Properties>() {
@@ -127,12 +124,10 @@ public class CompactDecimalFormat extends Format.BeforeFormat {
     if (rounder == null) {
       int _minSig = properties.getMinimumSignificantDigits();
       int _maxSig = properties.getMaximumSignificantDigits();
-      SignificantDigitsMode _mode = properties.getSignificantDigitsMode();
       Properties rprops = threadLocalProperties.get().clear();
       // Settings needing possible override:
       rprops.setMinimumSignificantDigits(_minSig > 0 ? _minSig : DEFAULT_MIN_SIG);
       rprops.setMaximumSignificantDigits(_maxSig > 0 ? _maxSig : DEFAULT_MAX_SIG);
-      rprops.setSignificantDigitsMode(_mode != null ? _mode : DEFAULT_SIG_MODE);
       // TODO: Should copyFrom() be used instead?  It requires a cast.
       // Settings to copy verbatim:
       rprops.setRoundingMode(properties.getRoundingMode());
index 63f1cc1cd1d69b051ca31e7e0517c3631d295079..98385a9dc5698bade1f3e833795cea2bdc94d93e 100644 (file)
@@ -17,16 +17,36 @@ public class SimpleModifier extends Modifier.BaseModifier {
   private final Field field;
   private final boolean strong;
 
+  private final int prefixLength;
+  private final int suffixOffset;
+  private final int suffixLength;
+
+  private static final int ARG_NUM_LIMIT = 0x100;
+
   /** Creates a modifier that uses the SimpleFormatter string formats. */
   public SimpleModifier(String compiledPattern, Field field, boolean strong) {
     this.compiledPattern = (compiledPattern == null) ? "\u0001\u0000" : compiledPattern;
     this.field = field;
     this.strong = strong;
+
+    assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
+    if (compiledPattern.charAt(1) != '\u0000') {
+      prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
+      suffixOffset = 3 + prefixLength;
+    } else {
+      prefixLength = 0;
+      suffixOffset = 2;
+    }
+    if (3 + prefixLength < compiledPattern.length()) {
+      suffixLength = compiledPattern.charAt(suffixOffset) - ARG_NUM_LIMIT;
+    } else {
+      suffixLength = 0;
+    }
   }
 
   @Override
   public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
-    return formatAsPrefixSuffix(compiledPattern, output, leftIndex, rightIndex, field);
+    return formatAsPrefixSuffix(output, leftIndex, rightIndex, field);
   }
 
   @Override
@@ -36,14 +56,18 @@ public class SimpleModifier extends Modifier.BaseModifier {
 
   @Override
   public String getPrefix() {
-    // TODO: Implement this when MeasureFormat is ready.
-    throw new UnsupportedOperationException();
+    if (prefixLength == 0) {
+      return "";
+    }
+    return compiledPattern.substring(2, 2 + prefixLength);
   }
 
   @Override
   public String getSuffix() {
-    // TODO: Implement this when MeasureFormat is ready.
-    throw new UnsupportedOperationException();
+    if (suffixLength == 0) {
+      return "";
+    }
+    return compiledPattern.substring(1 + suffixOffset, 1 + suffixOffset + suffixLength);
   }
 
   /**
@@ -57,38 +81,26 @@ public class SimpleModifier extends Modifier.BaseModifier {
    *
    * <p>This is well-defined only for patterns with exactly one argument.
    *
-   * @param compiledPattern Compiled form of a pattern string.
    * @param result The StringBuilder containing the value argument.
    * @param startIndex The left index of the value within the string builder.
    * @param endIndex The right index of the value within the string builder.
    * @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
    */
-  public static int formatAsPrefixSuffix(
-      String compiledPattern,
-      NumberStringBuilder result,
-      int startIndex,
-      int endIndex,
-      Field field) {
+  public int formatAsPrefixSuffix(
+      NumberStringBuilder result, int startIndex, int endIndex, Field field) {
     assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
-    int ARG_NUM_LIMIT = 0x100;
-    int length = 0, offset = 2;
-    if (compiledPattern.charAt(1) != '\u0000') {
-      int prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
-      if (result != null) {
-        result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
-      }
-      length += prefixLength;
-      offset = 3 + prefixLength;
+    if (prefixLength > 0) {
+      result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
     }
-    if (offset < compiledPattern.length()) {
-      int suffixLength = compiledPattern.charAt(offset) - ARG_NUM_LIMIT;
-      if (result != null) {
-        result.insert(
-            endIndex + length, compiledPattern, offset + 1, offset + suffixLength + 1, field);
-      }
-      length += suffixLength;
+    if (suffixLength > 0) {
+      result.insert(
+          endIndex + prefixLength,
+          compiledPattern,
+          1 + suffixOffset,
+          1 + suffixOffset + suffixLength,
+          field);
     }
-    return length;
+    return prefixLength + suffixLength;
   }
 
   /** TODO: Move this to a test file somewhere, once we figure out what to do with the method. */
@@ -108,8 +120,8 @@ public class SimpleModifier extends Modifier.BaseModifier {
             SimpleFormatterImpl.compileToStringMinMaxArguments(pattern, new StringBuilder(), 1, 1);
         NumberStringBuilder output = new NumberStringBuilder();
         output.append((String) outputs[j][0], null);
-        formatAsPrefixSuffix(
-            compiledPattern, output, (Integer) outputs[j][1], (Integer) outputs[j][2], null);
+        new SimpleModifier(compiledPattern, null, false)
+            .apply(output, (Integer) outputs[j][1], (Integer) outputs[j][2]);
         String expected = expecteds[j][i];
         String actual = output.toString();
         assert expected.equals(actual);
index 7959b8973b8218d9f51d133a7335f661fceff6c2..23977c384b7b09215de9538f38f51ee97612abfa 100644 (file)
@@ -7,7 +7,6 @@ import java.math.RoundingMode;
 import com.ibm.icu.impl.number.FormatQuantity;
 import com.ibm.icu.impl.number.Properties;
 import com.ibm.icu.impl.number.Rounder;
-import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
 
 public class SignificantDigitsRounder extends Rounder {
 
@@ -65,28 +64,13 @@ public class SignificantDigitsRounder extends Rounder {
      * @return The property bag, for chaining.
      */
     public IProperties setMaximumSignificantDigits(int maximumSignificantDigits);
-
-    static SignificantDigitsMode DEFAULT_SIGNIFICANT_DIGITS_MODE = null;
-
-    /** @see #setSignificantDigitsMode */
-    public SignificantDigitsMode getSignificantDigitsMode();
-
-    /**
-     * Sets the strategy used when reconciling significant digits versus integer and fraction
-     * lengths.
-     *
-     * @param significantDigitsMode One of the options from {@link SignificantDigitsMode}.
-     * @return The property bag, for chaining.
-     */
-    public IProperties setSignificantDigitsMode(SignificantDigitsMode significantDigitsMode);
   }
 
   public static boolean useSignificantDigits(IProperties properties) {
     return properties.getMinimumSignificantDigits()
             != IProperties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS
         || properties.getMaximumSignificantDigits()
-            != IProperties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS
-        || properties.getSignificantDigitsMode() != IProperties.DEFAULT_SIGNIFICANT_DIGITS_MODE;
+            != IProperties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS;
   }
 
   public static SignificantDigitsRounder getInstance(IProperties properties) {
@@ -95,7 +79,6 @@ public class SignificantDigitsRounder extends Rounder {
 
   private final int minSig;
   private final int maxSig;
-  private final SignificantDigitsMode mode;
 
   private SignificantDigitsRounder(IProperties properties) {
     super(properties);
@@ -103,8 +86,6 @@ public class SignificantDigitsRounder extends Rounder {
     int _maxSig = properties.getMaximumSignificantDigits();
     minSig = _minSig < 1 ? 1 : _minSig > 1000 ? 1000 : _minSig;
     maxSig = _maxSig < 0 ? 1000 : _maxSig < minSig ? minSig : _maxSig > 1000 ? 1000 : _maxSig;
-    SignificantDigitsMode _mode = properties.getSignificantDigitsMode();
-    mode = _mode == null ? SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION : _mode;
   }
 
   @Override
@@ -123,47 +104,7 @@ public class SignificantDigitsRounder extends Rounder {
     magMaxSig = effectiveMag - maxSig;
 
     // Step 1: pick the rounding magnitude and apply.
-    int roundingMagnitude;
-    switch (mode) {
-      case OVERRIDE_MAXIMUM_FRACTION:
-        // Always round to maxSig.
-        // Of the six possible orders:
-        //    Case 1: minSig, maxSig, minFrac, maxFrac -- maxSig wins
-        //    Case 2: minSig, minFrac, maxSig, maxFrac -- maxSig wins
-        //    Case 3: minSig, minFrac, maxFrac, maxSig -- maxSig wins
-        //    Case 4: minFrac, minSig, maxSig, maxFrac -- maxSig wins
-        //    Case 5: minFrac, minSig, maxFrac, maxSig -- maxSig wins
-        //    Case 6: minFrac, maxFrac, minSig, maxSig -- maxSig wins
-        roundingMagnitude = magMaxSig;
-        break;
-      case RESPECT_MAXIMUM_FRACTION:
-        // Round to the strongest of maxFrac, maxInt, and maxSig.
-        // Of the six possible orders:
-        //    Case 1: minSig, maxSig, minFrac, maxFrac -- maxSig wins
-        //    Case 2: minSig, minFrac, maxSig, maxFrac -- maxSig wins
-        //    Case 3: minSig, minFrac, maxFrac, maxSig -- maxFrac wins --> differs from default
-        //    Case 4: minFrac, minSig, maxSig, maxFrac -- maxSig wins
-        //    Case 5: minFrac, minSig, maxFrac, maxSig -- maxFrac wins --> differs from default
-        //    Case 6: minFrac, maxFrac, minSig, maxSig -- maxFrac wins --> differs from default
-        //
-        // Math.max() picks the rounding magnitude farthest to the left (most significant).
-        // Math.min() picks the rounding magnitude farthest to the right (least significant).
-        roundingMagnitude = Math.max(-maxFrac, magMaxSig);
-        break;
-      case ENSURE_MINIMUM_SIGNIFICANT:
-        // Round to the strongest of maxFrac and maxSig, and always ensure minSig.
-        // Of the six possible orders:
-        //    Case 1: minSig, maxSig, minFrac, maxFrac -- maxSig wins
-        //    Case 2: minSig, minFrac, maxSig, maxFrac -- maxSig wins
-        //    Case 3: minSig, minFrac, maxFrac, maxSig -- maxFrac wins --> differs from default
-        //    Case 4: minFrac, minSig, maxSig, maxFrac -- maxSig wins
-        //    Case 5: minFrac, minSig, maxFrac, maxSig -- maxFrac wins --> differs from default
-        //    Case 6: minFrac, maxFrac, minSig, maxSig -- minSig wins --> differs from default
-        roundingMagnitude = Math.min(magMinSig, Math.max(-maxFrac, magMaxSig));
-        break;
-      default:
-        throw new AssertionError();
-    }
+    int roundingMagnitude = magMaxSig;
     input.roundToMagnitude(roundingMagnitude, mathContext);
 
     // In case magnitude changed:
@@ -177,23 +118,8 @@ public class SignificantDigitsRounder extends Rounder {
     magMaxSig = effectiveMag - maxSig;
 
     // Step 2: pick the number of visible digits.
-    switch (mode) {
-      case OVERRIDE_MAXIMUM_FRACTION:
-        // Ensure minSig is always displayed.
-        input.setIntegerLength(minInt, maxInt);
-        input.setFractionLength(Math.max(minFrac, -magMinSig), Integer.MAX_VALUE);
-        break;
-      case RESPECT_MAXIMUM_FRACTION:
-        // Ensure minSig is displayed, unless doing so is in violation of maxFrac.
-        input.setIntegerLength(minInt, maxInt);
-        input.setFractionLength(Math.min(maxFrac, Math.max(minFrac, -magMinSig)), maxFrac);
-        break;
-      case ENSURE_MINIMUM_SIGNIFICANT:
-        // Follow minInt/minFrac, but ensure all digits are allowed to be visible.
-        input.setIntegerLength(minInt, maxInt);
-        input.setFractionLength(minFrac, Integer.MAX_VALUE);
-        break;
-    }
+    input.setIntegerLength(minInt, maxInt);
+    input.setFractionLength(Math.max(minFrac, -magMinSig), Integer.MAX_VALUE);
   }
 
   @Override
@@ -201,6 +127,5 @@ public class SignificantDigitsRounder extends Rounder {
     super.export(properties);
     properties.setMinimumSignificantDigits(minSig);
     properties.setMaximumSignificantDigits(maxSig);
-    properties.setSignificantDigitsMode(mode);
   }
 }
index eaa5ca40d35c65b041c07df43d02edae70227886..3442c0ebc0f2bd024cec1242989e3d0d91c1e773 100644 (file)
@@ -12,7 +12,6 @@ package com.ibm.icu.text;
 import java.text.ParsePosition;
 import java.util.Locale;
 
-import com.ibm.icu.impl.number.PatternString;
 import com.ibm.icu.impl.number.Properties;
 import com.ibm.icu.util.CurrencyAmount;
 import com.ibm.icu.util.ULocale;
@@ -121,17 +120,13 @@ public class CompactDecimalFormat extends DecimalFormat {
    * @param style the compact style
    */
   CompactDecimalFormat(ULocale locale, CompactStyle style) {
-    // Use the locale's default pattern
-    String pattern = getPattern(locale, 0);
+    // Minimal properties: let the non-shim code path do most of the logic for us.
     symbols = DecimalFormatSymbols.getInstance(locale);
     properties = new Properties();
     properties.setCompactStyle(style);
+    properties.setGroupingSize(-2); // do not forward grouping information
+    properties.setMinimumGroupingDigits(2);
     exportedProperties = new Properties();
-    setPropertiesFromPattern(pattern, PatternString.IGNORE_ROUNDING_ALWAYS);
-    if (style == CompactStyle.SHORT) {
-      // TODO: This was setGroupingUsed(false) in ICU 58. Is it okay that I changed it for ICU 59?
-      properties.setMinimumGroupingDigits(2);
-    }
     refreshFormatter();
   }
 
index dfcd84db3ea2a91bc0a570a8f74a13aa94e03331..7fb96a2eb4d31cfa03056378da2bc186d0f28eb6 100644 (file)
@@ -13,9 +13,6 @@ import java.text.FieldPosition;
 import java.text.ParseException;
 import java.text.ParsePosition;
 
-import com.ibm.icu.impl.number.Endpoint;
-import com.ibm.icu.impl.number.Format.SingularFormat;
-import com.ibm.icu.impl.number.FormatQuantity4;
 import com.ibm.icu.impl.number.Parse;
 import com.ibm.icu.impl.number.PatternString;
 import com.ibm.icu.impl.number.Properties;
@@ -33,6 +30,12 @@ import com.ibm.icu.util.CurrencyAmount;
 import com.ibm.icu.util.ULocale;
 import com.ibm.icu.util.ULocale.Category;
 
+import newapi.NumberFormatter.LocalizedNumberFormatter;
+import newapi.NumberFormatter.NumberFormatterResult;
+import newapi.impl.MacroProps;
+import newapi.impl.NumberFormatterImpl;
+import newapi.impl.NumberPropertyMapper;
+
 /**
  * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_} <code>DecimalFormat</code> is the primary
  * concrete subclass of {@link NumberFormat}. It has a variety of features designed to make it
@@ -107,9 +110,8 @@ import com.ibm.icu.util.ULocale.Category;
  *       digits are shown. This is most common in scientific notation.
  * </ol>
  *
- * <p>It is possible to specify both a magnitude and a number of significant digits. If used
- * together, the <em>significant digits mode</em> determines how conflicts between fraction digits
- * and signiciant digits are resolved. For more information, see {@link #setSignificantDigitsMode}.
+ * <p>It is not possible to specify more than one rounding strategy. For example, setting a rounding
+ * increment in conjunction with significant digits results in undefined behavior.
  *
  * <p>It is also possible to specify the <em>rounding mode</em> to use. The default rounding mode is
  * "half even", which rounds numbers to their closest increment, with ties broken in favor of
@@ -265,7 +267,7 @@ public class DecimalFormat extends NumberFormat {
    * #format} method uses the formatter directly without needing to synchronize. Volatile because
    * threads may read and write at the same time.
    */
-  transient volatile SingularFormat formatter;
+  transient volatile LocalizedNumberFormatter formatter;
 
   /**
    * The effective properties as exported from the formatter object. Volatile because threads may
@@ -683,9 +685,9 @@ public class DecimalFormat extends NumberFormat {
    */
   @Override
   public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
-    FormatQuantity4 fq = new FormatQuantity4(number);
-    formatter.format(fq, result, fieldPosition);
-    fq.populateUFieldPosition(fieldPosition);
+    NumberFormatterResult output = formatter.format(number);
+    output.populateFieldPosition(fieldPosition, result.length());
+    output.appendTo(result);
     return result;
   }
 
@@ -696,9 +698,9 @@ public class DecimalFormat extends NumberFormat {
    */
   @Override
   public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
-    FormatQuantity4 fq = new FormatQuantity4(number);
-    formatter.format(fq, result, fieldPosition);
-    fq.populateUFieldPosition(fieldPosition);
+    NumberFormatterResult output = formatter.format(number);
+    output.populateFieldPosition(fieldPosition, result.length());
+    output.appendTo(result);
     return result;
   }
 
@@ -709,9 +711,9 @@ public class DecimalFormat extends NumberFormat {
    */
   @Override
   public StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition) {
-    FormatQuantity4 fq = new FormatQuantity4(number);
-    formatter.format(fq, result, fieldPosition);
-    fq.populateUFieldPosition(fieldPosition);
+    NumberFormatterResult output = formatter.format(number);
+    output.populateFieldPosition(fieldPosition, result.length());
+    output.appendTo(result);
     return result;
   }
 
@@ -723,9 +725,9 @@ public class DecimalFormat extends NumberFormat {
   @Override
   public StringBuffer format(
       java.math.BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
-    FormatQuantity4 fq = new FormatQuantity4(number);
-    formatter.format(fq, result, fieldPosition);
-    fq.populateUFieldPosition(fieldPosition);
+    NumberFormatterResult output = formatter.format(number);
+    output.populateFieldPosition(fieldPosition, result.length());
+    output.appendTo(result);
     return result;
   }
 
@@ -736,9 +738,9 @@ public class DecimalFormat extends NumberFormat {
    */
   @Override
   public StringBuffer format(BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
-    FormatQuantity4 fq = new FormatQuantity4(number.toBigDecimal());
-    formatter.format(fq, result, fieldPosition);
-    fq.populateUFieldPosition(fieldPosition);
+    NumberFormatterResult output = formatter.format(number);
+    output.populateFieldPosition(fieldPosition, result.length());
+    output.appendTo(result);
     return result;
   }
 
@@ -751,9 +753,8 @@ public class DecimalFormat extends NumberFormat {
   public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
     if (!(obj instanceof Number)) throw new IllegalArgumentException();
     Number number = (Number) obj;
-    FormatQuantity4 fq = new FormatQuantity4(number);
-    AttributedCharacterIterator result = formatter.formatToCharacterIterator(fq);
-    return result;
+    NumberFormatterResult output = formatter.format(number);
+    return output.toAttributedCharacterIterator();
   }
 
   /**
@@ -763,27 +764,9 @@ public class DecimalFormat extends NumberFormat {
    */
   @Override
   public StringBuffer format(CurrencyAmount currAmt, StringBuffer toAppendTo, FieldPosition pos) {
-    // TODO: This is ugly (although not as ugly as it was in ICU 58).
-    // Currency should be a free parameter, not in property bag. Fix in ICU 60.
-    Properties cprops = threadLocalProperties.get();
-    SingularFormat fmt = null;
-    synchronized (this) {
-      // Use the pre-compiled formatter if possible.  Otherwise, copy the properties
-      // and build our own formatter.
-      // TODO: Consider using a static format path here.
-      if (currAmt.getCurrency().equals(properties.getCurrency())) {
-        fmt = formatter;
-      } else {
-        cprops.copyFrom(properties);
-      }
-    }
-    if (fmt == null) {
-      cprops.setCurrency(currAmt.getCurrency());
-      fmt = Endpoint.fromBTA(cprops, symbols);
-    }
-    FormatQuantity4 fq = new FormatQuantity4(currAmt.getNumber());
-    fmt.format(fq, toAppendTo, pos);
-    fq.populateUFieldPosition(pos);
+    NumberFormatterResult output = formatter.format(currAmt);
+    output.populateFieldPosition(pos, toAppendTo.length());
+    output.appendTo(toAppendTo);
     return toAppendTo;
   }
 
@@ -815,8 +798,11 @@ public class DecimalFormat extends NumberFormat {
   @Override
   public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosition) {
     try {
-      // TODO(sffc): Make this thread-safe
-      CurrencyAmount result = Parse.parseCurrency(text, parsePosition, properties, symbols);
+      Properties pprops = threadLocalProperties.get();
+      synchronized (this) {
+        pprops.copyFrom(properties);
+      }
+      CurrencyAmount result = Parse.parseCurrency(text, parsePosition, pprops, symbols);
       if (result == null) return null;
       Number number = result.getNumber();
       // Backwards compatibility: return com.ibm.icu.math.BigDecimal
@@ -872,8 +858,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized String getPositivePrefix() {
-    String result = exportedProperties.getPositivePrefix();
-    return (result == null) ? "" : result;
+    return formatter.format(1).getPrefix();
   }
 
   /**
@@ -910,8 +895,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized String getNegativePrefix() {
-    String result = exportedProperties.getNegativePrefix();
-    return (result == null) ? "" : result;
+    return formatter.format(-1).getPrefix();
   }
 
   /**
@@ -948,8 +932,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized String getPositiveSuffix() {
-    String result = exportedProperties.getPositiveSuffix();
-    return (result == null) ? "" : result;
+    return formatter.format(1).getSuffix();
   }
 
   /**
@@ -986,8 +969,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized String getNegativeSuffix() {
-    String result = exportedProperties.getNegativeSuffix();
-    return (result == null) ? "" : result;
+    return formatter.format(-1).getSuffix();
   }
 
   /**
@@ -1516,7 +1498,6 @@ public class DecimalFormat extends NumberFormat {
     } else {
       properties.setMinimumSignificantDigits(Properties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS);
       properties.setMaximumSignificantDigits(Properties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS);
-      properties.setSignificantDigitsMode(null);
     }
     refreshFormatter();
   }
@@ -1545,7 +1526,6 @@ public class DecimalFormat extends NumberFormat {
    * and then you set maxInt=3, then minInt will be changed to 3.
    *
    * @param value The minimum number of significant digits to display.
-   * @see #setSignificantDigitsMode
    * @category Rounding
    * @stable ICU 3.0
    */
@@ -1588,7 +1568,6 @@ public class DecimalFormat extends NumberFormat {
    * @see #setRoundingMode
    * @see #setRoundingIncrement
    * @see #setMaximumFractionDigits
-   * @see #setSignificantDigitsMode
    * @category Rounding
    * @stable ICU 3.0
    */
@@ -1601,60 +1580,6 @@ public class DecimalFormat extends NumberFormat {
     refreshFormatter();
   }
 
-  /**
-   * {@icu} Returns the current significant digits mode.
-   *
-   * @see #setSignificantDigitsMode
-   * @category Rounding
-   * @internal
-   * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
-   */
-  @Deprecated
-  public synchronized SignificantDigitsMode getSignificantDigitsMode() {
-    return exportedProperties.getSignificantDigitsMode();
-  }
-
-  /**
-   * {@icu} <strong>Rounding and Digit Limits:</strong> Sets the strategy used for resolving
-   * minimum/maximum significant digits when minimum/maximum integer and/or fraction digits are
-   * specified. There are three modes:
-   *
-   * <ul>
-   *   <li>Mode A: OVERRIDE_MAXIMUM_FRACTION. This is the default. Settings in maximum fraction are
-   *       ignored.
-   *   <li>Mode B: RESPECT_MAXIMUM_FRACTION. Round to maximum fraction even if doing so will prevent
-   *       minimum significant from being respected.
-   *   <li>Mode C: ENSURE_MINIMUM_SIGNIFICANT. Respect maximum fraction, but always ensure that
-   *       minimum significant digits are shown.
-   * </ul>
-   *
-   * <p>The following table illustrates the difference. Below, minFrac=1, maxFrac=2, minSig=3, and
-   * maxSig=4:
-   *
-   * <pre>
-   *   Mode A |   Mode B |   Mode C
-   * ---------+----------+----------
-   *  12340.0 |  12340.0 |  12340.0
-   *   1234.0 |   1234.0 |   1234.0
-   *    123.4 |    123.4 |    123.4
-   *    12.34 |    12.34 |    12.34
-   *    1.234 |     1.23 |     1.23
-   *   0.1234 |     0.12 |    0.123
-   *  0.01234 |     0.01 |   0.0123
-   * 0.001234 |     0.00 |  0.00123
-   * </pre>
-   *
-   * @param mode The significant digits mode to use.
-   * @category Rounding
-   * @internal
-   * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
-   */
-  @Deprecated
-  public synchronized void setSignificantDigitsMode(SignificantDigitsMode mode) {
-    properties.setSignificantDigitsMode(mode);
-    refreshFormatter();
-  }
-
   /**
    * Returns the minimum number of characters in formatted output.
    *
@@ -1663,7 +1588,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized int getFormatWidth() {
-    return exportedProperties.getFormatWidth();
+    return properties.getFormatWidth();
   }
 
   /**
@@ -1699,7 +1624,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized char getPadCharacter() {
-    CharSequence paddingString = exportedProperties.getPadString();
+    CharSequence paddingString = properties.getPadString();
     if (paddingString == null) {
       return '.'; // TODO: Is this the correct behavior?
     } else {
@@ -1732,7 +1657,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized int getPadPosition() {
-    PadPosition loc = exportedProperties.getPadPosition();
+    PadPosition loc = properties.getPadPosition();
     return (loc == null) ? PAD_BEFORE_PREFIX : loc.toOld();
   }
 
@@ -1800,7 +1725,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized byte getMinimumExponentDigits() {
-    return (byte) exportedProperties.getMinimumExponentDigits();
+    return (byte) properties.getMinimumExponentDigits();
   }
 
   /**
@@ -1828,7 +1753,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized boolean isExponentSignAlwaysShown() {
-    return exportedProperties.getExponentSignAlwaysShown();
+    return properties.getExponentSignAlwaysShown();
   }
 
   /**
@@ -1898,7 +1823,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized int getGroupingSize() {
-    return exportedProperties.getGroupingSize();
+    return properties.getGroupingSize();
   }
 
   /**
@@ -1930,7 +1855,12 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized int getSecondaryGroupingSize() {
-    return exportedProperties.getSecondaryGroupingSize();
+    int grouping1 = properties.getGroupingSize();
+    int grouping2 = properties.getSecondaryGroupingSize();
+    if (grouping1 == grouping2 || grouping2 < 0) {
+      return 0;
+    }
+    return properties.getSecondaryGroupingSize();
   }
 
   /**
@@ -1991,7 +1921,7 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 2.0
    */
   public synchronized boolean isDecimalSeparatorAlwaysShown() {
-    return exportedProperties.getDecimalSeparatorAlwaysShown();
+    return properties.getDecimalSeparatorAlwaysShown();
   }
 
   /**
@@ -2471,9 +2401,7 @@ public class DecimalFormat extends NumberFormat {
    */
   @Deprecated
   public IFixedDecimal getFixedDecimal(double number) {
-    FormatQuantity4 fq = new FormatQuantity4(number);
-    formatter.format(fq);
-    return fq;
+    return formatter.format(number).getFixedDecimal();
   }
 
   private static final ThreadLocal<Properties> threadLocalProperties =
@@ -2491,9 +2419,18 @@ public class DecimalFormat extends NumberFormat {
       // The only time when this happens is during legacy deserialization.
       return;
     }
-    formatter = Endpoint.fromBTA(properties, symbols);
-    exportedProperties.clear();
-    formatter.export(exportedProperties);
+    MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, exportedProperties);
+    ULocale locale = this.getLocale(ULocale.ACTUAL_LOCALE);
+    if (locale == null) {
+      // Constructor
+      locale = symbols.getLocale(ULocale.ACTUAL_LOCALE);
+    }
+    if (locale == null) {
+      // Deserialization
+      locale = symbols.getULocale();
+    }
+    assert locale != null;
+    formatter = NumberFormatterImpl.fromMacros(macros).locale(locale);
   }
 
   /**
@@ -2561,46 +2498,6 @@ public class DecimalFormat extends NumberFormat {
     public void set(Properties props);
   }
 
-  /**
-   * An enum containing the choices for significant digits modes.
-   *
-   * @see #setSignificantDigitsMode
-   * @internal
-   * @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
-   */
-  @Deprecated
-  public static enum SignificantDigitsMode {
-    /**
-     * Respect significant digits counts, ignoring the fraction length.
-     *
-     * @see DecimalFormat#setSignificantDigitsMode
-     * @internal
-     * @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
-     */
-    @Deprecated
-    OVERRIDE_MAXIMUM_FRACTION,
-
-    /**
-     * Respect the fraction length, overriding significant digits counts if necessary.
-     *
-     * @see DecimalFormat#setSignificantDigitsMode
-     * @internal
-     * @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
-     */
-    @Deprecated
-    RESPECT_MAXIMUM_FRACTION,
-
-    /**
-     * Respect minimum significant digits, overriding fraction length if necessary.
-     *
-     * @see DecimalFormat#setSignificantDigitsMode
-     * @internal
-     * @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
-     */
-    @Deprecated
-    ENSURE_MINIMUM_SIGNIFICANT
-  }
-
   /**
    * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
    * characters inserted before the prefix.
index 5200bc83d6f70cba33811490936351c05690f18c..005158e024e84850a1f157900c7ef5c8c1683cd8 100644 (file)
@@ -259,8 +259,8 @@ $**####,##0 1234    $***1\u00a0234  K
 // In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
 \u00a4\u00a4 **####0.00        433.0   EUR *433,00     JK
 // In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
-// S fails this one because the test code bypasses CurrencyUsage
-\u00a4\u00a4 **#######0        433.0   EUR *433,00     JKS
+// S and Q fail this one because the test code bypasses CurrencyUsage
+\u00a4\u00a4 **#######0        433.0   EUR *433,00     JKSQ
 
 test padding and currencies
 begin
@@ -338,8 +338,8 @@ minIntegerDigits    maxIntegerDigits        minFractionDigits       maxFractionDigits       output  bre
 // JDK gives E0 instead of allowing for unlimited precision
 // S obeys the maximum integer digits and returns .299792458E9
 0      0       0       0       2.99792458E8    KS
-// JDK and S give .299792E9
-0      1       0       5       2.9979E8        KS
+// JDK and S give .299792E9; Q gives 2.99792E8
+0      1       0       5       2.9979E8        KSQ
 // JDK gives 300E6     
 0      3       0       0       299.792458E6    K
 // JDK gives 299.8E6 (maybe maxInt + maxFrac instead of minInt + maxFrac)?
@@ -356,12 +356,13 @@ minIntegerDigits  maxIntegerDigits        minFractionDigits       maxFractionDigits       output  bre
 // JDK gives E0
 // S obeys the maximum integer digits
 0      0       1       0       2.99792458E8    KS
-// JDK gives .2998E9
-0      0       0       4       2.998E8 KS
+// JDK and S give .2998E9
+0      0       0       4       2.998E8 KSQ
 // S correctly formats this as 29.979246E7.
 // JDK uses 8 + 6 for significant digits instead of 2 + 6
 // J and C return 2.9979246E8.
-2      8       1       6       29.979246E7     CJK
+// TODO: Merge trunk
+2      8       1       6       29.979246E7     CJKQ
 // Treat max int digits > 8 as being the same as min int digits.
 // This behavior is not spelled out in the specification.
 // JDK fails here because it tries to use 9 + 6 = 15 sig digits.
@@ -405,12 +406,12 @@ begin
 format maxIntegerDigits        output  breaks
 123    1       3       
 0      0       0
-// S ignores max integer if it is less than zero and prints "123"
-123    -2147483648     0       S
+// S and Q ignore max integer if it is less than zero and prints "123"
+123    -2147483648     0       SQ
 12345  1       5       
-12345  -2147483648     0       S
+12345  -2147483648     0       SQ
 5.3    1       5.3     
-5.3    -2147483648     .3      S
+5.3    -2147483648     .3      SQ
 
 test patterns with zero
 set locale en
@@ -489,8 +490,9 @@ output      grouping        breaks  grouping2       minGroupingDigits
 1,2345,6789    4
 1,23,45,6789   4       K       2
 1,23,45,6789   4       K       2       2
+// Q only supports minGrouping<=2
 123,456789     6               6       3
-123456789      6       JK      6       4
+123456789      6       JKQ     6       4
 
 test multiplier setters
 set locale en_US
@@ -498,8 +500,10 @@ begin
 format multiplier      output  breaks
 23     -12     -276
 23     -1      -23
-// ICU4J and JDK throw exception on zero multiplier. ICU4C does not.
-23     0       23      JKS
+// ICU4J and JDK throw exception on zero multiplier.
+// ICU4C and S print 23.
+// Q multiplies by zero and prints 0.
+23     0       0       CJKS
 23     1       23
 23     12      276
 -23    12      -276
@@ -513,8 +517,9 @@ begin
 format output  breaks
 -0.35  -0.25   K
 0.35   0.25    K
-0.39   0.5     K
-0.62   0.5     K
+// Q doesn't support mixing minFrac with roundingIncrement (prints 0.50).
+0.39   0.5     KQ
+0.62   0.5     KQ
 0.63   0.75    K
 
 test padding setters
@@ -539,20 +544,19 @@ output    breaks  useScientific
 
 test rounding mode setters
 set locale en_US
-set pattern 0.#
-set roundingIncrement 0.5
+set pattern 0.5
 begin
 format roundingMode    output  breaks
-1.24   halfUp  1       K
+1.24   halfUp  1.0     K
 1.25   halfUp  1.5     K
-1.25   halfDown        1       K
+1.25   halfDown        1.0     K
 1.26   halfDown        1.5     K
-1.25   halfEven        1       K
+1.25   halfEven        1.0     K
 -1.01  up      -1.5    K
--1.49  down    -1      K
+-1.49  down    -1.0    K
 1.01   up      1.5     K
-1.49   down    1       K
--1.01  ceiling -1
+1.49   down    1.0     K
+-1.01  ceiling -1.0
 -1.49  floor   -1.5
 
 test currency usage setters
@@ -584,7 +588,7 @@ set locale en
 set currency USD
 begin
 pattern        format  output  breaks
-#      123     123     S
+#      123     123     SQ
 // Currency rounding should always override the pattern.
 // K prints the currency in ISO format for some reason.
 \u00a4#        123     $123.00 K
@@ -659,7 +663,8 @@ begin
 format output  breaks
 Inf    [\u221e]
 -Inf   (\u221e)        K
-NaN    NaN     K
+// Q prints the affixes
+NaN    NaN     KQ
 
 test nan and infinity with multiplication
 set locale en
@@ -680,10 +685,11 @@ Inf       beforePrefix      $$$\u221e$    K
 Inf    afterPrefix     $$$  \u221e$    K
 Inf    beforeSuffix    $$$\u221e  $    K
 Inf    afterSuffix     $$$\u221e$      K
-NaN    beforePrefix        NaN K
-NaN    afterPrefix         NaN K
-NaN    beforeSuffix    NaN     K
-NaN    afterSuffix     NaN     K
+// Q gets $$$NaN$
+NaN    beforePrefix        NaN KQ
+NaN    afterPrefix         NaN KQ
+NaN    beforeSuffix    NaN     KQ
+NaN    afterSuffix     NaN     KQ
 
 test apply formerly localized patterns
 begin
@@ -1540,8 +1546,9 @@ set maxSigDigits 2
 begin
 format output  breaks
 // C and J get "1"
+// Q gets "1.0"
 // K gets "1.1" (??)
-0.975  0.98    CJK
+0.975  0.98    CJKQ
 
 test lenient parse currency match
 // This test is for #13112
index 7e3f34e81312b2427e3f9cea275c9f85cc410204..db5e74a7f3c34e5f8dea37698aa248ceb1d216b0 100644 (file)
@@ -102,7 +102,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
             {1234567890123f, "1,2 билиона"},
             {12345678901234f, "12 билиона"},
             {123456789012345f, "120 билиона"},
-            {1234567890123456f, "1.200 билиона"},
+            {1234567890123456f, "1200 билиона"},
     };
 
     Object[][] SerbianTestDataLongNegative = {
@@ -125,7 +125,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
             {-1234567890123f, "-1,2 билиона"},
             {-12345678901234f, "-12 билиона"},
             {-123456789012345f, "-120 билиона"},
-            {-1234567890123456f, "-1.200 билиона"},
+            {-1234567890123456f, "-1200 билиона"},
     };
 
     Object[][] JapaneseTestData = {
@@ -363,10 +363,10 @@ public class CompactDecimalFormatTest extends TestFmwk {
         // and rounded to the unit for compact formats with three or more zeros.
         CompactDecimalFormat cdf =
                 CompactDecimalFormat.getInstance(ULocale.ENGLISH, CompactStyle.SHORT);
-        assertEquals("Default significant digits", "120K", cdf.format(123456));
+        assertEquals("Default significant digits", "123K", cdf.format(123456));
         assertEquals("Default significant digits", "12K", cdf.format(12345));
         assertEquals("Default significant digits", "1.2K", cdf.format(1234));
-        assertEquals("Default significant digits", "120", cdf.format(123));
+        assertEquals("Default significant digits", "123", cdf.format(123));
     }
 
     @Test
@@ -636,8 +636,9 @@ public class CompactDecimalFormatTest extends TestFmwk {
     public void TestDigitDisplay() {
         CompactDecimalFormat cdf = CompactDecimalFormat.getInstance(ULocale.US, CompactStyle.SHORT);
         cdf.setMinimumSignificantDigits(2);
+        cdf.setMaximumSignificantDigits(3);
         String actual = cdf.format(70123.45678);
-        assertEquals("Should not display any extra fraction digits", "70K", actual);
+        assertEquals("Should not display any extra fraction digits", "70.1K", actual);
     }
 
     @Test
@@ -667,7 +668,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
                 props.setCompactCustomData(customData);
             }
         });
-        assertEquals("Below custom range", "120", cdf.format(123));
+        assertEquals("Below custom range", "123", cdf.format(123));
         assertEquals("Plural form one", "1 qwerty", cdf.format(1000));
         assertEquals("Plural form other", "1.2 dvorak", cdf.format(1234));
         assertEquals("Above custom range", "12 dvorak", cdf.format(12345));
index 9f28b1c057d5418ec6f9e1e93c95666e0c303c6a..e4ce633a7f4eb61800ee21a71809ca29c2475fd8 100644 (file)
@@ -59,8 +59,7 @@ public class IntlTestDecimalFormatAPI extends com.ibm.icu.dev.test.TestFmwk
         String pat = ",##0.0000";
         DecimalFormat dec = new DecimalFormat(pat);
         dec.setRoundingMode(BigDecimal.ROUND_HALF_UP);
-        double roundinginc = 0.0001;
-        dec.setRoundingIncrement(roundinginc);
+        dec.setRoundingIncrement(new java.math.BigDecimal("0.0001"));
         String str = dec.format(number);
         if (!str.equals(expected)) {
             errln("Fail: " + number + " x \"" + pat + "\" = \"" +
index 3532ed1e33b97961e17d4047a4e1441d15e29b1e..82c9aa44eddafc8aa4e05258101a5c51502ae337 100644 (file)
@@ -278,7 +278,7 @@ public class IntlTestDecimalFormatAPIC extends com.ibm.icu.dev.test.TestFmwk {
             }
 
             //for +2.55 with RoundingIncrement=1.0
-            pat.setRoundingIncrement(1.0);
+            pat.setRoundingIncrement(java.math.BigDecimal.ONE);
             resultStr = pat.format(Roundingnumber);
             message = "round(" + Roundingnumber
                     + "," + mode + ",FALSE) with RoundingIncrement=1.0==>";
index 77495f41d342271d3025ef47eb6d4cb4e0f39be6..690aa55212df8246f6dbb8e8891788456e884a63 100644 (file)
@@ -124,7 +124,7 @@ public class IntlTestDecimalFormatSymbolsC extends com.ibm.icu.dev.test.TestFmwk
         sym.setPercent('P');
         verify(34.5, "00 %", sym, "3450 P");
         sym.setCurrencySymbol("D");
-        verify(34.5, "\u00a4##.##", sym, "D34.50");
+        verify(34.5, "\u00a4##.##", sym, "D 34.50");
         sym.setGroupingSeparator('|');
         verify(3456.5, "0,000.##", sym, "3|456S5");
     }
index 14de333161ef9313f2fea52d2479557989a6ed2e..12f0b43b300118a1cab67c2feac19ec1110f8685 100644 (file)
@@ -1660,9 +1660,9 @@ public class MeasureUnitTest extends TestFmwk {
         assertEquals("Wide currency", "1.00 US dollars", mf.format(USD_1));
         assertEquals("Wide currency", "2.00 US dollars", mf.format(USD_2));
         mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT);
-        assertEquals("short currency", "-USD1.00", mf.format(USD_NEG_1));
-        assertEquals("short currency", "USD1.00", mf.format(USD_1));
-        assertEquals("short currency", "USD2.00", mf.format(USD_2));
+        assertEquals("short currency", "-USD 1.00", mf.format(USD_NEG_1));
+        assertEquals("short currency", "USD 1.00", mf.format(USD_1));
+        assertEquals("short currency", "USD 2.00", mf.format(USD_2));
         mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NARROW);
         assertEquals("narrow currency", "-$1.00", mf.format(USD_NEG_1));
         assertEquals("narrow currency", "$1.00", mf.format(USD_1));
@@ -1673,13 +1673,13 @@ public class MeasureUnitTest extends TestFmwk {
         assertEquals("numeric currency", "$2.00", mf.format(USD_2));
 
         mf = MeasureFormat.getInstance(ULocale.JAPAN, FormatWidth.WIDE);
-        assertEquals("Wide currency", "-1.00\u7C73\u30C9\u30EB", mf.format(USD_NEG_1));
-        assertEquals("Wide currency", "1.00\u7C73\u30C9\u30EB", mf.format(USD_1));
-        assertEquals("Wide currency", "2.00\u7C73\u30C9\u30EB", mf.format(USD_2));
+        assertEquals("Wide currency", "-1.00 \u7C73\u30C9\u30EB", mf.format(USD_NEG_1));
+        assertEquals("Wide currency", "1.00 \u7C73\u30C9\u30EB", mf.format(USD_1));
+        assertEquals("Wide currency", "2.00 \u7C73\u30C9\u30EB", mf.format(USD_2));
 
         Measure CAD_1 = new Measure(1.0, Currency.getInstance("CAD"));
         mf = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.SHORT);
-        assertEquals("short currency", "CAD1.00", mf.format(CAD_1));
+        assertEquals("short currency", "CAD 1.00", mf.format(CAD_1));
     }
 
     @Test
@@ -1997,7 +1997,10 @@ public class MeasureUnitTest extends TestFmwk {
             }
         }
         for (String type : MeasureUnit.getAvailableTypes()) {
-            if (type.equals("currency") || type.equals("compound") || type.equals("coordinate")) {
+            if (type.equals("currency")
+                    || type.equals("compound")
+                    || type.equals("coordinate")
+                    || type.equals("dimensionless")) {
                 continue;
             }
             for (MeasureUnit unit : MeasureUnit.getAvailable(type)) {
index c1c5bf07890c86f60c5432a100d952c3f212d092..8cd8d2a632007b73187a998da6d1e3c3e70b5686 100644 (file)
@@ -7,6 +7,7 @@ import java.math.RoundingMode;
 import java.text.ParseException;
 import java.text.ParsePosition;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
 import com.ibm.icu.dev.test.TestUtil;
@@ -29,6 +30,11 @@ import com.ibm.icu.text.DecimalFormat_ICU58;
 import com.ibm.icu.util.CurrencyAmount;
 import com.ibm.icu.util.ULocale;
 
+import newapi.NumberFormatter.LocalizedNumberFormatter;
+import newapi.impl.MacroProps;
+import newapi.impl.NumberFormatterImpl;
+import newapi.impl.NumberPropertyMapper;
+
 public class NumberFormatDataDrivenTest {
 
   private static ULocale EN = new ULocale("en");
@@ -431,7 +437,7 @@ public class NumberFormatDataDrivenTest {
         }
       };
 
-  private DataDrivenNumberFormatTestUtility.CodeUnderTest Shane =
+  private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU59 =
       new DataDrivenNumberFormatTestUtility.CodeUnderTest() {
 
         @Override
@@ -667,117 +673,154 @@ public class NumberFormatDataDrivenTest {
         public String select(DataDrivenNumberFormatTestData tuple) {
           return null;
         }
+      };
 
-        private void propertiesFromTuple(
-            DataDrivenNumberFormatTestData tuple, Properties properties) {
-          if (tuple.minIntegerDigits != null) {
-            properties.setMinimumIntegerDigits(tuple.minIntegerDigits);
-          }
-          if (tuple.maxIntegerDigits != null) {
-            properties.setMaximumIntegerDigits(tuple.maxIntegerDigits);
-          }
-          if (tuple.minFractionDigits != null) {
-            properties.setMinimumFractionDigits(tuple.minFractionDigits);
-          }
-          if (tuple.maxFractionDigits != null) {
-            properties.setMaximumFractionDigits(tuple.maxFractionDigits);
-          }
-          if (tuple.currency != null) {
-            properties.setCurrency(tuple.currency);
-          }
-          if (tuple.minGroupingDigits != null) {
-            properties.setMinimumGroupingDigits(tuple.minGroupingDigits);
-          }
-          if (tuple.useSigDigits != null) {
-            // TODO
-          }
-          if (tuple.minSigDigits != null) {
-            properties.setMinimumSignificantDigits(tuple.minSigDigits);
-          }
-          if (tuple.maxSigDigits != null) {
-            properties.setMaximumSignificantDigits(tuple.maxSigDigits);
-          }
-          if (tuple.useGrouping != null && tuple.useGrouping == 0) {
-            properties.setGroupingSize(-1);
-            properties.setSecondaryGroupingSize(-1);
-          }
-          if (tuple.multiplier != null) {
-            properties.setMultiplier(new BigDecimal(tuple.multiplier));
-          }
-          if (tuple.roundingIncrement != null) {
-            properties.setRoundingIncrement(new BigDecimal(tuple.roundingIncrement.toString()));
-          }
-          if (tuple.formatWidth != null) {
-            properties.setFormatWidth(tuple.formatWidth);
-          }
-          if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) {
-            properties.setPadString(tuple.padCharacter.toString());
-          }
-          if (tuple.useScientific != null) {
-            properties.setMinimumExponentDigits(
-                tuple.useScientific != 0 ? 1 : Properties.DEFAULT_MINIMUM_EXPONENT_DIGITS);
-          }
-          if (tuple.grouping != null) {
-            properties.setGroupingSize(tuple.grouping);
-          }
-          if (tuple.grouping2 != null) {
-            properties.setSecondaryGroupingSize(tuple.grouping2);
-          }
-          if (tuple.roundingMode != null) {
-            properties.setRoundingMode(RoundingMode.valueOf(tuple.roundingMode));
-          }
-          if (tuple.currencyUsage != null) {
-            properties.setCurrencyUsage(tuple.currencyUsage);
-          }
-          if (tuple.minimumExponentDigits != null) {
-            properties.setMinimumExponentDigits(tuple.minimumExponentDigits.byteValue());
-          }
-          if (tuple.exponentSignAlwaysShown != null) {
-            properties.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0);
-          }
-          if (tuple.decimalSeparatorAlwaysShown != null) {
-            properties.setDecimalSeparatorAlwaysShown(tuple.decimalSeparatorAlwaysShown != 0);
-          }
-          if (tuple.padPosition != null) {
-            properties.setPadPosition(PadPosition.fromOld(tuple.padPosition));
-          }
-          if (tuple.positivePrefix != null) {
-            properties.setPositivePrefix(tuple.positivePrefix);
-          }
-          if (tuple.positiveSuffix != null) {
-            properties.setPositiveSuffix(tuple.positiveSuffix);
-          }
-          if (tuple.negativePrefix != null) {
-            properties.setNegativePrefix(tuple.negativePrefix);
-          }
-          if (tuple.negativeSuffix != null) {
-            properties.setNegativeSuffix(tuple.negativeSuffix);
-          }
-          if (tuple.localizedPattern != null) {
-            DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(tuple.locale);
-            String converted =
-                PatternString.convertLocalized(tuple.localizedPattern, symbols, false);
-            PatternString.parseToExistingProperties(converted, properties);
-          }
-          if (tuple.lenient != null) {
-            properties.setParseMode(tuple.lenient == 0 ? ParseMode.STRICT : ParseMode.LENIENT);
-          }
-          if (tuple.parseIntegerOnly != null) {
-            properties.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
-          }
-          if (tuple.parseCaseSensitive != null) {
-            properties.setParseCaseSensitive(tuple.parseCaseSensitive != 0);
-          }
-          if (tuple.decimalPatternMatchRequired != null) {
-            properties.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0);
-          }
-          if (tuple.parseNoExponent != null) {
-            properties.setParseNoExponent(tuple.parseNoExponent != 0);
+  static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, Properties properties) {
+    if (tuple.minIntegerDigits != null) {
+      properties.setMinimumIntegerDigits(tuple.minIntegerDigits);
+    }
+    if (tuple.maxIntegerDigits != null) {
+      properties.setMaximumIntegerDigits(tuple.maxIntegerDigits);
+    }
+    if (tuple.minFractionDigits != null) {
+      properties.setMinimumFractionDigits(tuple.minFractionDigits);
+    }
+    if (tuple.maxFractionDigits != null) {
+      properties.setMaximumFractionDigits(tuple.maxFractionDigits);
+    }
+    if (tuple.currency != null) {
+      properties.setCurrency(tuple.currency);
+    }
+    if (tuple.minGroupingDigits != null) {
+      properties.setMinimumGroupingDigits(tuple.minGroupingDigits);
+    }
+    if (tuple.useSigDigits != null) {
+      // TODO
+    }
+    if (tuple.minSigDigits != null) {
+      properties.setMinimumSignificantDigits(tuple.minSigDigits);
+    }
+    if (tuple.maxSigDigits != null) {
+      properties.setMaximumSignificantDigits(tuple.maxSigDigits);
+    }
+    if (tuple.useGrouping != null && tuple.useGrouping == 0) {
+      properties.setGroupingSize(-1);
+      properties.setSecondaryGroupingSize(-1);
+    }
+    if (tuple.multiplier != null) {
+      properties.setMultiplier(new BigDecimal(tuple.multiplier));
+    }
+    if (tuple.roundingIncrement != null) {
+      properties.setRoundingIncrement(new BigDecimal(tuple.roundingIncrement.toString()));
+    }
+    if (tuple.formatWidth != null) {
+      properties.setFormatWidth(tuple.formatWidth);
+    }
+    if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) {
+      properties.setPadString(tuple.padCharacter.toString());
+    }
+    if (tuple.useScientific != null) {
+      properties.setMinimumExponentDigits(
+          tuple.useScientific != 0 ? 1 : Properties.DEFAULT_MINIMUM_EXPONENT_DIGITS);
+    }
+    if (tuple.grouping != null) {
+      properties.setGroupingSize(tuple.grouping);
+    }
+    if (tuple.grouping2 != null) {
+      properties.setSecondaryGroupingSize(tuple.grouping2);
+    }
+    if (tuple.roundingMode != null) {
+      properties.setRoundingMode(RoundingMode.valueOf(tuple.roundingMode));
+    }
+    if (tuple.currencyUsage != null) {
+      properties.setCurrencyUsage(tuple.currencyUsage);
+    }
+    if (tuple.minimumExponentDigits != null) {
+      properties.setMinimumExponentDigits(tuple.minimumExponentDigits.byteValue());
+    }
+    if (tuple.exponentSignAlwaysShown != null) {
+      properties.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0);
+    }
+    if (tuple.decimalSeparatorAlwaysShown != null) {
+      properties.setDecimalSeparatorAlwaysShown(tuple.decimalSeparatorAlwaysShown != 0);
+    }
+    if (tuple.padPosition != null) {
+      properties.setPadPosition(PadPosition.fromOld(tuple.padPosition));
+    }
+    if (tuple.positivePrefix != null) {
+      properties.setPositivePrefix(tuple.positivePrefix);
+    }
+    if (tuple.positiveSuffix != null) {
+      properties.setPositiveSuffix(tuple.positiveSuffix);
+    }
+    if (tuple.negativePrefix != null) {
+      properties.setNegativePrefix(tuple.negativePrefix);
+    }
+    if (tuple.negativeSuffix != null) {
+      properties.setNegativeSuffix(tuple.negativeSuffix);
+    }
+    if (tuple.localizedPattern != null) {
+      DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(tuple.locale);
+      String converted = PatternString.convertLocalized(tuple.localizedPattern, symbols, false);
+      PatternString.parseToExistingProperties(converted, properties);
+    }
+    if (tuple.lenient != null) {
+      properties.setParseMode(tuple.lenient == 0 ? ParseMode.STRICT : ParseMode.LENIENT);
+    }
+    if (tuple.parseIntegerOnly != null) {
+      properties.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
+    }
+    if (tuple.parseCaseSensitive != null) {
+      properties.setParseCaseSensitive(tuple.parseCaseSensitive != 0);
+    }
+    if (tuple.decimalPatternMatchRequired != null) {
+      properties.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0);
+    }
+    if (tuple.parseNoExponent != null) {
+      properties.setParseNoExponent(tuple.parseNoExponent != 0);
+    }
+  }
+
+  private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU60 =
+      new DataDrivenNumberFormatTestUtility.CodeUnderTest() {
+
+        @Override
+        public Character Id() {
+          return 'Q';
+        }
+
+        /**
+         * Runs a single formatting test. On success, returns null. On failure, returns the error.
+         * This implementation just returns null. Subclasses should override.
+         *
+         * @param tuple contains the parameters of the format test.
+         */
+        @Override
+        public String format(DataDrivenNumberFormatTestData tuple) {
+          String pattern = (tuple.pattern == null) ? "0" : tuple.pattern;
+          ULocale locale = (tuple.locale == null) ? ULocale.ENGLISH : tuple.locale;
+          Properties properties =
+              PatternString.parseToProperties(
+                  pattern,
+                  tuple.currency != null
+                      ? PatternString.IGNORE_ROUNDING_ALWAYS
+                      : PatternString.IGNORE_ROUNDING_NEVER);
+          propertiesFromTuple(tuple, properties);
+          DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
+          MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, null);
+          LocalizedNumberFormatter fmt = NumberFormatterImpl.fromMacros(macros).locale(locale);
+          Number number = toNumber(tuple.format);
+          String expected = tuple.output;
+          String actual = fmt.format(number).toString();
+          if (!expected.equals(actual)) {
+            return "Expected \"" + expected + "\", got \"" + actual + "\"";
           }
+          return null;
         }
       };
 
   @Test
+  @Ignore
   public void TestDataDrivenICU58() {
     // Android can't access DecimalFormat_ICU58 for testing (ticket #13283).
     if (TestUtil.getJavaVendor() == TestUtil.JavaVendor.Android) return;
@@ -787,14 +830,22 @@ public class NumberFormatDataDrivenTest {
   }
 
   @Test
+  @Ignore
   public void TestDataDrivenJDK() {
     DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
         "numberformattestspecification.txt", JDK);
   }
 
   @Test
-  public void TestDataDrivenShane() {
+  @Ignore
+  public void TestDataDrivenICU59() {
+    DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
+        "numberformattestspecification.txt", ICU59);
+  }
+
+  @Test
+  public void TestDataDrivenICU60() {
     DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
-        "numberformattestspecification.txt", Shane);
+        "numberformattestspecification.txt", ICU60);
   }
 }
index d7d1f600efc5ecdf536d8dd9a90c3b93bf86db02..1916d87617fa8cc73551b33ea5a52ffa935f3f1d 100644 (file)
@@ -76,7 +76,7 @@ public class NumberFormatRegressionTest extends com.ibm.icu.dev.test.TestFmwk {
         // or this (with changes to fr_CH per cldrbug:9370):
         //nf.setGroupingUsed(false);
         // so they are done in DateFormat.setNumberFormat
-    
+
         // create the DateFormat
         DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, loc);
 
@@ -185,7 +185,8 @@ public class NumberFormatRegressionTest extends com.ibm.icu.dev.test.TestFmwk {
                 String result = format.format(data);
                 assertEquals("Deserialization new version should read old version", expected[i], result);
             } catch (Exception e) {
-                warnln("FAIL: " + e.getMessage());
+                e.printStackTrace();
+                warnln("FAIL: " + e);
             }
         }
     }
index 8012fd4061f1068db0448dbbf44230f96c382364..c67a916ff5f59771332dbc01b82470d949a2820a 100644 (file)
@@ -50,7 +50,6 @@ import com.ibm.icu.text.CompactDecimalFormat;
 import com.ibm.icu.text.CurrencyPluralInfo;
 import com.ibm.icu.text.DecimalFormat;
 import com.ibm.icu.text.DecimalFormat.PropertySetter;
-import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
 import com.ibm.icu.text.DecimalFormatSymbols;
 import com.ibm.icu.text.DecimalFormat_ICU58;
 import com.ibm.icu.text.DisplayContext;
@@ -500,13 +499,13 @@ public class NumberFormatTest extends TestFmwk {
                 // currency format using currency ISO name, such as "USD",
                 // currency format using plural name, such as "US dollars".
                 // for US locale
-                {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"},
-                {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"},
-                {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollars1.00"},
+                {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD 1,234.56", "US dollars 1,234.56"},
+                {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD 1,234.56", "-US dollars 1,234.56"},
+                {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD 1.00", "US dollars 1.00"},
                 // for CHINA locale
-                {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY1,234.56", "\u4EBA\u6C11\u5E011,234.56"},
-                {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY1,234.56)", "(\u4EBA\u6C11\u5E011,234.56)"},
-                {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY1.00", "\u4EBA\u6C11\u5E011.00"}
+                {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY 1,234.56", "\u4EBA\u6C11\u5E01 1,234.56"},
+                {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY 1,234.56)", "(\u4EBA\u6C11\u5E01 1,234.56)"},
+                {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY 1.00", "\u4EBA\u6C11\u5E01 1.00"}
         };
 
         String doubleCurrencyStr = "\u00A4\u00A4";
@@ -536,7 +535,7 @@ public class NumberFormatTest extends TestFmwk {
                 // 'j' number of currency sign.
                 String currencyFormatResult = DATA[i][2+j];
                 if (!s.equals(currencyFormatResult)) {
-                    errln("FAIL format: Expected " + currencyFormatResult);
+                    errln("FAIL format: Expected " + currencyFormatResult + " but got " + s);
                 }
                 try {
                     // mix style parsing
@@ -712,13 +711,13 @@ public class NumberFormatTest extends TestFmwk {
                 // format result using CURRENCYSTYLE,
                 // format result using ISOCURRENCYSTYLE,
                 // format result using PLURALCURRENCYSTYLE,
-                {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"},
-                {"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
-                {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
-                {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00美元"},
-                {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56美元"},
-                {"zh_CN", "1", "CNY", "¥1.00", "CNY1.00", "1.00人民币"},
-                {"zh_CN", "1234.56", "CNY", "¥1,234.56", "CNY1,234.56", "1,234.56人民币"},
+                {"en_US", "1", "USD", "$1.00", "USD 1.00", "1.00 US dollars"},
+                {"en_US", "1234.56", "USD", "$1,234.56", "USD 1,234.56", "1,234.56 US dollars"},
+                {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD 1,234.56", "-1,234.56 US dollars"},
+                {"zh_CN", "1", "USD", "US$1.00", "USD 1.00", "1.00 美元"},
+                {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD 1,234.56", "1,234.56 美元"},
+                {"zh_CN", "1", "CNY", "¥1.00", "CNY 1.00", "1.00 人民币"},
+                {"zh_CN", "1234.56", "CNY", "¥1,234.56", "CNY 1,234.56", "1,234.56 人民币"},
                 {"ru_RU", "1", "RUB", "1,00 \u20BD", "1,00 RUB", "1,00 российского рубля"},
                 {"ru_RU", "2", "RUB", "2,00 \u20BD", "2,00 RUB", "2,00 российского рубля"},
                 {"ru_RU", "5", "RUB", "5,00 \u20BD", "5,00 RUB", "5,00 российского рубля"},
@@ -957,7 +956,7 @@ public class NumberFormatTest extends TestFmwk {
                 1234.56, "\u00A51,235"); // Yen
 
         expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
-                1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
+                1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
 
         expectCurrency(fmt, Currency.getInstance(Locale.US),
                 1234.56, "$1,234.56");
@@ -1727,7 +1726,7 @@ public class NumberFormatTest extends TestFmwk {
         ULocale locale = new ULocale("th_TH@currency=QQQ");
         NumberFormat format = NumberFormat.getCurrencyInstance(locale);
         String result = format.format(12.34f);
-        if (!"QQQ12.34".equals(result)) {
+        if (!"QQQ 12.34".equals(result)) {
             errln("got unexpected currency: " + result);
         }
     }
@@ -2255,13 +2254,13 @@ public class NumberFormatTest extends TestFmwk {
         nf.setCurrency(Currency.getInstance(new Locale("fr", "ch", "")));
         StringBuffer buffer2 = new StringBuffer();
         nf.format(amount, buffer2, cp);
-        assertEquals("CHF35.47", "CHF35.47", buffer2.toString());
+        assertEquals("CHF 35.47", "CHF 35.47", buffer2.toString());
         assertEquals("cp begin", 0, cp.getBeginIndex());
         assertEquals("cp end", 3, cp.getEndIndex());
 
         StringBuffer buffer20 = new StringBuffer();
         nf.format(negAmount, buffer20, cp);
-        assertEquals("-CHF34.57", "-CHF34.57", buffer20.toString());
+        assertEquals("-CHF 34.57", "-CHF 34.57", buffer20.toString());
         assertEquals("cp begin", 1, cp.getBeginIndex());
         assertEquals("cp end", 4, cp.getEndIndex());
 
@@ -2296,17 +2295,17 @@ public class NumberFormatTest extends TestFmwk {
         plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
         StringBuffer buffer7 = new StringBuffer();
         plCurrencyFmt.format(amount, buffer7, cp);
-        assertEquals("35.47スイス フラン", "35.47スイス フラン", buffer7.toString());
-        assertEquals("cp begin", 5, cp.getBeginIndex());
-        assertEquals("cp end", 12, cp.getEndIndex());
+        assertEquals("35.47 スイス フラン", "35.47 スイス フラン", buffer7.toString());
+        assertEquals("cp begin", 6, cp.getBeginIndex());
+        assertEquals("cp end", 13, cp.getEndIndex());
 
         // PLURALCURRENCYSTYLE for non-ASCII.
         plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "de"), NumberFormat.PLURALCURRENCYSTYLE);
         StringBuffer buffer8 = new StringBuffer();
         plCurrencyFmt.format(negAmount, buffer8, cp);
-        assertEquals("-34.57ユーロ", "-34.57ユーロ", buffer8.toString());
-        assertEquals("cp begin", 6, cp.getBeginIndex());
-        assertEquals("cp end", 9, cp.getEndIndex());
+        assertEquals("-34.57 ユーロ", "-34.57 ユーロ", buffer8.toString());
+        assertEquals("cp begin", 7, cp.getBeginIndex());
+        assertEquals("cp end", 10, cp.getEndIndex());
 
         nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(Locale.JAPAN);
         nf.setCurrency(Currency.getInstance(new Locale("ja", "jp")));
@@ -2320,9 +2319,9 @@ public class NumberFormatTest extends TestFmwk {
         plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
         StringBuffer buffer10 = new StringBuffer();
         plCurrencyFmt.format(negAmount, buffer10, cp);
-        assertEquals("-34.57スイス フラン", "-34.57スイス フラン", buffer10.toString());
-        assertEquals("cp begin", 6, cp.getBeginIndex());
-        assertEquals("cp end", 13, cp.getEndIndex());
+        assertEquals("-34.57 スイス フラン", "-34.57 スイス フラン", buffer10.toString());
+        assertEquals("cp begin", 7, cp.getBeginIndex());
+        assertEquals("cp end", 14, cp.getEndIndex());
 
         // Nagative value with PLURALCURRENCYSTYLE, Arabic digits.
         nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(new Locale("ar", "eg"));
@@ -2362,11 +2361,11 @@ public class NumberFormatTest extends TestFmwk {
     public void TestRoundingPattern() {
         class TestRoundingPatternItem {
             String     pattern;
-            double     roundingIncrement;
+            BigDecimal roundingIncrement;
             double     testCase;
             String     expected;
 
-            TestRoundingPatternItem(String pattern, double roundingIncrement, double testCase, String expected) {
+            TestRoundingPatternItem(String pattern, BigDecimal roundingIncrement, double testCase, String expected) {
                 this.pattern = pattern;
                 this.roundingIncrement = roundingIncrement;
                 this.testCase = testCase;
@@ -2375,13 +2374,12 @@ public class NumberFormatTest extends TestFmwk {
         };
 
         TestRoundingPatternItem []tests = {
-                new TestRoundingPatternItem("##0.65", 0.65, 1.234, "1.30"),
-                new TestRoundingPatternItem("#50", 50.0, 1230, "1250")
+                new TestRoundingPatternItem("##0.65", new BigDecimal("0.65"), 1.234, "1.30"),
+                new TestRoundingPatternItem("#50", new BigDecimal("50"), 1230, "1250")
         };
 
         DecimalFormat df = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
         String result;
-        BigDecimal bd;
         for (int i = 0; i < tests.length; i++) {
             df.applyPattern(tests[i].pattern);
 
@@ -2391,9 +2389,7 @@ public class NumberFormatTest extends TestFmwk {
                 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
             }
 
-            bd = new BigDecimal(tests[i].roundingIncrement);
-
-            df.setRoundingIncrement(bd);
+            df.setRoundingIncrement(tests[i].roundingIncrement);
 
             result = df.format(tests[i].testCase);
 
@@ -4130,7 +4126,7 @@ public class NumberFormatTest extends TestFmwk {
         // * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that
         // * CAD rounds to .05 in the cash style only.
         for (int i = 0; i < 2; i++) {
-            String original_expected = "PKR124";
+            String original_expected = "PKR 124";
             DecimalFormat custom = null;
             if (i == 0) {
                 custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=PKR"),
@@ -4153,7 +4149,7 @@ public class NumberFormatTest extends TestFmwk {
             }
 
             String cash_currency = custom.format(123.567);
-            String cash_currency_expected = "PKR124";
+            String cash_currency_expected = "PKR 124";
             assertEquals("Test Currency Context", cash_currency_expected, cash_currency);
         }
 
@@ -4195,7 +4191,7 @@ public class NumberFormatTest extends TestFmwk {
 
             fmt2.setCurrency(Currency.getInstance("PKR"));
             String PKR_changed = fmt2.format(123.567);
-            String PKR_changed_expected = "PKR124";
+            String PKR_changed_expected = "PKR 124";
             assertEquals("Test Currency Context", PKR_changed_expected, PKR_changed);
         }
     }
@@ -4744,7 +4740,7 @@ public class NumberFormatTest extends TestFmwk {
         fmt.setDecimalFormatSymbols(symbols);
         fmt.applyPattern("#,##0.0#");
         assertEquals("Custom decimal and grouping separator string with multiple characters",
-                fmt.format(1234567.89), "(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)");
+                "(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)", fmt.format(1234567.89));
 
         // Digits starting at U+1D7CE MATHEMATICAL BOLD DIGIT ZERO
         // These are all single code points, so parsing will work.
@@ -4917,7 +4913,7 @@ public class NumberFormatTest extends TestFmwk {
         DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
         df.applyPattern("¤¤¤ 0");
         String result = df.getPositivePrefix();
-        assertEquals("Triple-currency should give long name on getPositivePrefix", "US dollars ", result);
+        assertEquals("Triple-currency should give long name on getPositivePrefix", "US dollar ", result);
     }
 
     @Test
@@ -5263,7 +5259,7 @@ public class NumberFormatTest extends TestFmwk {
         symbols.setCurrencySymbol("#");
         df.setDecimalFormatSymbols(symbols);
         String actual = df.format(123);
-        assertEquals("Should use '#' instad of '$'", "#123.00", actual);
+        assertEquals("Should use '#' instad of '$'", "# 123.00", actual);
     }
 
     @Test
@@ -5478,9 +5474,9 @@ public class NumberFormatTest extends TestFmwk {
         df.setMaximumFractionDigits(3);
         expect2(df, 35.0, "$35.000");
         df.setMinimumFractionDigits(-1);
+        expect2(df, 35.0, "$35");
+        df.setMaximumFractionDigits(-1);
         expect2(df, 35.0, "$35.00");
-        df.setMaximumFractionDigits(1);
-        expect2(df, 35.0, "$35.0");
     }
 
     @Test
@@ -5637,46 +5633,6 @@ public class NumberFormatTest extends TestFmwk {
         }
     }
 
-    @Test
-    public void testSignificantDigitsMode() {
-        String[][] allExpected = {
-              {"12340.0", "12340.0", "12340.0"},
-              {"1234.0", "1234.0", "1234.0"},
-              {"123.4", "123.4", "123.4"},
-              {"12.34", "12.34", "12.34"},
-              {"1.234", "1.23", "1.23"},
-              {"0.1234", "0.12", "0.123"},
-              {"0.01234", "0.01", "0.0123"},
-              {"0.001234", "0.00", "0.00123"}
-        };
-
-        DecimalFormat df = new DecimalFormat();
-        df.setMinimumFractionDigits(1);
-        df.setMaximumFractionDigits(2);
-        df.setMinimumSignificantDigits(3);
-        df.setMaximumSignificantDigits(4);
-        df.setGroupingUsed(false);
-
-        SignificantDigitsMode[] modes = new SignificantDigitsMode[] {
-                SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION,
-                SignificantDigitsMode.RESPECT_MAXIMUM_FRACTION,
-                SignificantDigitsMode.ENSURE_MINIMUM_SIGNIFICANT
-        };
-
-        for (double d = 12340.0, i=0; d > 0.001; d /= 10, i++) {
-            for (int j=0; j<modes.length; j++) {
-                SignificantDigitsMode mode = modes[j];
-                df.setSignificantDigitsMode(mode);
-                String expected = allExpected[(int)i][j];
-                String actual = df.format(d);
-                assertEquals("Significant digits mode getter is broken",
-                        mode, df.getSignificantDigitsMode());
-                assertEquals("Significant digits output differs for "+i+", "+j,
-                        expected, actual);
-            }
-        }
-    }
-
     @Test
     public void testParseNoExponent() throws ParseException {
         DecimalFormat df = new DecimalFormat();
index e1ba90826bc42b607c61053fcbe16d5dd32950fa..14b52190170c081183a7d14c135e2097f68315fc 100644 (file)
@@ -82,13 +82,13 @@ fpc: -              1234.56/JPY  "¥1,235"  1235/JPY
 # ISO codes that overlap display names (QQQ vs. Q)
 # fake ISO code is not longer supported
 # fpc: -              123/QQQ      "QQQ123.00"    123/QQQ   # QQQ is fake
-fpc: -              123/GTQ      "GTQ123.00"      123/GTQ
+fpc: -              123/GTQ      "GTQ 123.00"     123/GTQ
 # ChoiceFormat-based display names
 fpc: -              1/INR        "₹1.00"      1/INR
 
 fpc: -              2/INR        "₹2.00"      2/INR
 # Display names with shared prefix (YDD vs. Y)
-fpc: -              100/YDD      "YDD100.00"    100/YDD
+fpc: -              100/YDD      "YDD 100.00"     100/YDD
 fpc: -              100/CNY      "CN¥100.00"      100/CNY
 
 # Lenient Tests
index 0b03a846b7d72545bc9b4d356ec54b239fc8de54..83ce0ed32f63d3e6d22af51aa46c5c2a723878fd 100644 (file)
@@ -161,7 +161,7 @@ public class NumberRegressionTests extends TestFmwk {
         try {
             logln(df.format(123, sBuf, fp).toString());
         } catch (Exception foo) {
-            errln("Test for bug 4088503 failed.");
+            errln("Test for bug 4088503 failed: " + foo);
         }
 
     }
@@ -963,6 +963,7 @@ public class NumberRegressionTests extends TestFmwk {
         Locale.setDefault(Locale.US);
         DecimalFormat df = new DecimalFormat();
         df.setPositivePrefix("+");
+        df.setNegativePrefix("-");
         double d = -0.0;
         logln("pattern: \"" + df.toPattern() + "\"");
         StringBuffer buffer = new StringBuffer();
@@ -999,6 +1000,7 @@ public class NumberRegressionTests extends TestFmwk {
     {
         Locale[] locales = NumberFormat.getAvailableLocales();
 
+        outer:
         for (int i = 0; i < locales.length; i++) {
             ICUResourceBundle rb = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME,locales[i]);
 
@@ -1054,11 +1056,20 @@ public class NumberRegressionTests extends TestFmwk {
 
             String result2 = fmt2.format(1.111);
 
-            // NOTE: en_IN is a special case (ChoiceFormat currency display name)
-            if (!result1.equals(result2) &&
-                !locales[i].toString().equals("en_IN")) {
-                errln("Results for " + locales[i] + " differ: " +
-                      result1 + " vs " + result2);
+            // Currency spacing may have been added by the real DecimalFormat.  Account for that here.
+            if (!result1.equals(result2)) {
+                if (result1.length() == result2.length() + 1) {
+                    inner:
+                    for (int k=0; k<result2.length(); k++) {
+                        if (result1.charAt(k) != result2.charAt(k)) {
+                            if (result1.charAt(k) == '\u00A0') {
+                                continue outer; // currency spacing OK
+                            }
+                            break inner;
+                        }
+                    }
+                }
+                errln("Results for " + locales[i] + " differ: " + result1 + " vs " + result2);
             }
         }
     }
@@ -1483,9 +1494,9 @@ public class NumberRegressionTests extends TestFmwk {
         fmt.applyPattern("\u00A4#.00");
         sym.setCurrencySymbol("usd");
         fmt.setDecimalFormatSymbols(sym);
-        if (!fmt.format(12.5).equals("usd12.50")) {
+        if (!fmt.format(12.5).equals("usd 12.50")) {
             errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) +
-                  ", exp usd12.50");
+                  ", exp usd 12.50");
         }
         if (!fmt.getPositivePrefix().equals("usd")) {
             errln("FAIL: (currency=usd).getPositivePrefix -> " +
@@ -1496,9 +1507,9 @@ public class NumberRegressionTests extends TestFmwk {
         fmt.applyPattern("\u00A4\u00A4#.00");
         sym.setInternationalCurrencySymbol("DOL");
         fmt.setDecimalFormatSymbols(sym);
-        if (!fmt.format(12.5).equals("DOL12.50")) {
+        if (!fmt.format(12.5).equals("DOL 12.50")) {
             errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) +
-                  ", exp DOL12.50");
+                  ", exp DOL 12.50");
         }
         if (!fmt.getPositivePrefix().equals("DOL")) {
             errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " +
index 9d4e005b9048cbb48484d774d68144bc843c7445..7f64bf03a6ae2c95ec3d1f21d328078292332655 100644 (file)
@@ -37,7 +37,6 @@ import com.ibm.icu.impl.number.formatters.CurrencyFormat.CurrencyStyle;
 import com.ibm.icu.impl.number.formatters.PaddingFormat.PadPosition;
 import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
 import com.ibm.icu.text.CurrencyPluralInfo;
-import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
 import com.ibm.icu.text.MeasureFormat.FormatWidth;
 import com.ibm.icu.text.PluralRules;
 import com.ibm.icu.util.Currency;
@@ -306,11 +305,6 @@ public class PropertiesTest {
       RoundingMode[] values = RoundingMode.values();
       return values[seed % values.length];
 
-    } else if (type == SignificantDigitsMode.class) {
-      if (seed == 0) return null;
-      SignificantDigitsMode[] values = SignificantDigitsMode.values();
-      return values[seed % values.length];
-
     } else {
       fail("Don't know how to handle type " + type + ". Please add it to getSampleValueForType().");
       return null;
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/RounderTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/RounderTest.java
deleted file mode 100644 (file)
index f3001b5..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-// © 2017 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html#License
-package com.ibm.icu.dev.test.number;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-import com.ibm.icu.impl.number.FormatQuantity;
-import com.ibm.icu.impl.number.FormatQuantity4;
-import com.ibm.icu.impl.number.Properties;
-import com.ibm.icu.impl.number.rounders.SignificantDigitsRounder;
-import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
-
-public class RounderTest {
-
-  @Test
-  public void testSignificantDigitsRounder() {
-    Object[][][][] cases = {
-      {
-        {{1, -1}, {0, 2}, {2, 4}}, // minInt, maxInt, minFrac, maxFrac, minSig, maxSig
-        {
-          {0.0, "0.0", "0.0", "0"},
-          {0.054321, "0.05432", "0.05", "0.054"},
-          {0.54321, "0.5432", "0.54", "0.54"},
-          {1.0, "1.0", "1.0", "1"},
-          {5.4321, "5.432", "5.43", "5.43"},
-          {10.0, "10", "10", "10"},
-          {11.0, "11", "11", "11"},
-          {100.0, "100", "100", "100"},
-          {100.23, "100.2", "100.2", "100.2"},
-          {543210.0, "543200", "543200", "543200"},
-        }
-      },
-      {
-        {{1, -1}, {0, 0}, {2, -1}}, // minInt, maxInt, minFrac, maxFrac, minSig, maxSig
-        {
-          {0.0, "0.0", "0", "0"},
-          {0.054321, "0.054321", "0", "0.054"},
-          {0.54321, "0.54321", "1", "0.54"},
-          {1.0, "1.0", "1", "1"},
-          {5.4321, "5.4321", "5", "5.4"},
-          {10.0, "10", "10", "10"},
-          {11.0, "11", "11", "11"},
-          {100.0, "100", "100", "100"},
-          {100.23, "100.23", "100", "100"},
-          {543210.0, "543210", "543210", "543210"},
-        }
-      },
-      {
-        {{0, 2}, {1, 2}, {3, 3}}, // minInt, maxInt, minFrac, maxFrac, minSig, maxSig
-        {
-          {0.0, ".000", ".00", ".0"},
-          {0.054321, ".0543", ".05", ".0543"},
-          {0.54321, ".543", ".54", ".543"},
-          {1.0, "1.00", "1.00", "1.0"},
-          {5.4321, "5.43", "5.43", "5.43"},
-          {10.0, "10.0", "10.0", "10.0"},
-          {11.0, "11.0", "11.0", "11.0"},
-          {100.0, "00.0", "00.0", "00.0"},
-          {100.23, "00.2", "00.2", "00.2"},
-          {543210.0, "10.0", "10.0", "10.0"}
-        }
-      }
-    };
-
-    int caseNumber = 0;
-    for (Object[][][] cas : cases) {
-      int minInt = (Integer) cas[0][0][0];
-      int maxInt = (Integer) cas[0][0][1];
-      int minFrac = (Integer) cas[0][1][0];
-      int maxFrac = (Integer) cas[0][1][1];
-      int minSig = (Integer) cas[0][2][0];
-      int maxSig = (Integer) cas[0][2][1];
-
-      Properties properties = new Properties();
-      FormatQuantity4 fq = new FormatQuantity4();
-      properties.setMinimumIntegerDigits(minInt);
-      properties.setMaximumIntegerDigits(maxInt);
-      properties.setMinimumFractionDigits(minFrac);
-      properties.setMaximumFractionDigits(maxFrac);
-      properties.setMinimumSignificantDigits(minSig);
-      properties.setMaximumSignificantDigits(maxSig);
-
-      int runNumber = 0;
-      for (Object[] run : cas[1]) {
-        double input = (Double) run[0];
-        String expected1 = (String) run[1];
-        String expected2 = (String) run[2];
-        String expected3 = (String) run[3];
-
-        properties.setSignificantDigitsMode(SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION);
-        fq.setToDouble(input);
-        SignificantDigitsRounder.getInstance(properties).apply(fq);
-        assertEquals(
-            "Case " + caseNumber + ", run " + runNumber + ", mode 0: " + fq,
-            expected1,
-            formatQuantityToString(fq));
-
-        properties.setSignificantDigitsMode(SignificantDigitsMode.RESPECT_MAXIMUM_FRACTION);
-        fq.setToDouble(input);
-        SignificantDigitsRounder.getInstance(properties).apply(fq);
-        assertEquals(
-            "Case " + caseNumber + ", run " + runNumber + ", mode 1: " + fq,
-            expected2,
-            formatQuantityToString(fq));
-
-        properties.setSignificantDigitsMode(SignificantDigitsMode.ENSURE_MINIMUM_SIGNIFICANT);
-        fq.setToDouble(input);
-        SignificantDigitsRounder.getInstance(properties).apply(fq);
-        assertEquals(
-            "Case " + caseNumber + ", run " + runNumber + ", mode 2: " + fq,
-            expected3,
-            formatQuantityToString(fq));
-
-        runNumber++;
-      }
-
-      caseNumber++;
-    }
-  }
-
-  private String formatQuantityToString(FormatQuantity fq) {
-    StringBuilder sb = new StringBuilder();
-    int udm = fq.getUpperDisplayMagnitude();
-    int ldm = fq.getLowerDisplayMagnitude();
-    if (udm == -1) sb.append('.');
-    for (int m = udm; m >= ldm; m--) {
-      sb.append(fq.getDigit(m));
-      if (m == 0 && m > ldm) sb.append('.');
-    }
-    return sb.toString();
-  }
-}