ICU-13177 Changing more names of classes and moving code around. No behavior changes.

X-SVN-Rev: 40368
This commit is contained in:
Shane Carr 2017-09-02 04:53:46 +00:00
parent c0f2ca5177
commit a4905a73c0
41 changed files with 964 additions and 841 deletions

View file

@ -43,7 +43,7 @@ import com.ibm.icu.text.NumberFormat;
* }
* </pre>
*/
public class AffixPatternUtils {
public class AffixUtils {
private static final int STATE_BASE = 0;
private static final int STATE_FIRST_QUOTE = 1;
@ -296,7 +296,7 @@ public class AffixPatternUtils {
/**
* Checks whether the given affix pattern contains at least one token of the given type, which is
* one of the constants "TYPE_" in {@link AffixPatternUtils}.
* one of the constants "TYPE_" in {@link AffixUtils}.
*
* @param affixPattern The affix pattern to check.
* @param type The token type.

View file

@ -25,9 +25,9 @@ import com.ibm.icu.util.Currency.CurrencyUsage;
import newapi.impl.Padder.PadPosition;
public class Properties implements Cloneable, Serializable {
public class DecimalFormatProperties implements Cloneable, Serializable {
private static final Properties DEFAULT = new Properties();
private static final DecimalFormatProperties DEFAULT = new DecimalFormatProperties();
/** Auto-generated. */
private static final long serialVersionUID = 4095518955889349243L;
@ -98,7 +98,7 @@ public class Properties implements Cloneable, Serializable {
/| or #equals(), but it will NOT catch if you forget to add it to #hashCode(). |/
/+--------------------------------------------------------------------------------------------*/
public Properties() {
public DecimalFormatProperties() {
clear();
}
@ -114,7 +114,7 @@ public class Properties implements Cloneable, Serializable {
*
* @return The property bag, for chaining.
*/
private Properties _clear() {
private DecimalFormatProperties _clear() {
compactCustomData = null;
compactStyle = null;
currency = null;
@ -160,7 +160,7 @@ public class Properties implements Cloneable, Serializable {
return this;
}
private Properties _copyFrom(Properties other) {
private DecimalFormatProperties _copyFrom(DecimalFormatProperties other) {
compactCustomData = other.compactCustomData;
compactStyle = other.compactStyle;
currency = other.currency;
@ -206,7 +206,7 @@ public class Properties implements Cloneable, Serializable {
return this;
}
private boolean _equals(Properties other) {
private boolean _equals(DecimalFormatProperties other) {
boolean eq = true;
eq = eq && _equalsHelper(compactCustomData, other.compactCustomData);
eq = eq && _equalsHelper(compactStyle, other.compactStyle);
@ -327,16 +327,16 @@ public class Properties implements Cloneable, Serializable {
return value.hashCode();
}
public Properties clear() {
public DecimalFormatProperties clear() {
return _clear();
}
/** Creates and returns a shallow copy of the property bag. */
@Override
public Properties clone() {
public DecimalFormatProperties clone() {
// super.clone() returns a shallow copy.
try {
return (Properties) super.clone();
return (DecimalFormatProperties) super.clone();
} catch (CloneNotSupportedException e) {
// Should never happen since super is Object
throw new UnsupportedOperationException(e);
@ -349,7 +349,7 @@ public class Properties implements Cloneable, Serializable {
* @param other The property bag from which to copy and which will not be modified.
* @return The current property bag (the one modified by this operation), for chaining.
*/
public Properties copyFrom(Properties other) {
public DecimalFormatProperties copyFrom(DecimalFormatProperties other) {
return _copyFrom(other);
}
@ -357,8 +357,8 @@ public class Properties implements Cloneable, Serializable {
public boolean equals(Object other) {
if (other == null) return false;
if (this == other) return true;
if (!(other instanceof Properties)) return false;
return _equals((Properties) other);
if (!(other instanceof DecimalFormatProperties)) return false;
return _equals((DecimalFormatProperties) other);
}
/// BEGIN GETTERS/SETTERS ///
@ -557,7 +557,7 @@ public class Properties implements Cloneable, Serializable {
// Get the field reference
Field field = null;
try {
field = Properties.class.getDeclaredField(name);
field = DecimalFormatProperties.class.getDeclaredField(name);
} catch (NoSuchFieldException e) {
// The field name does not exist! Possibly corrupted serialization. Ignore this entry.
continue;
@ -605,7 +605,7 @@ public class Properties implements Cloneable, Serializable {
* @param compactCustomData A map with the above structure.
* @return The property bag, for chaining.
*/
public Properties setCompactCustomData(Map<String, Map<String, String>> compactCustomData) {
public DecimalFormatProperties setCompactCustomData(Map<String, Map<String, String>> compactCustomData) {
// TODO: compactCustomData is not immutable.
this.compactCustomData = compactCustomData;
return this;
@ -619,7 +619,7 @@ public class Properties implements Cloneable, Serializable {
* @param compactStyle The style of prefixes/suffixes to append.
* @return The property bag, for chaining.
*/
public Properties setCompactStyle(CompactStyle compactStyle) {
public DecimalFormatProperties setCompactStyle(CompactStyle compactStyle) {
this.compactStyle = compactStyle;
return this;
}
@ -630,7 +630,7 @@ public class Properties implements Cloneable, Serializable {
* @param currency The currency.
* @return The property bag, for chaining.
*/
public Properties setCurrency(Currency currency) {
public DecimalFormatProperties setCurrency(Currency currency) {
this.currency = currency;
return this;
}
@ -641,7 +641,7 @@ public class Properties implements Cloneable, Serializable {
* @param currencyPluralInfo The currency plural info object.
* @return The property bag, for chaining.
*/
public Properties setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo) {
public DecimalFormatProperties setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo) {
// TODO: In order to maintain immutability, we have to perform a clone here.
// It would be better to just retire CurrencyPluralInfo entirely.
if (currencyPluralInfo != null) {
@ -661,7 +661,7 @@ public class Properties implements Cloneable, Serializable {
* @param currencyUsage The currency usage. Defaults to CurrencyUsage.STANDARD.
* @return The property bag, for chaining.
*/
public Properties setCurrencyUsage(CurrencyUsage currencyUsage) {
public DecimalFormatProperties setCurrencyUsage(CurrencyUsage currencyUsage) {
this.currencyUsage = currencyUsage;
return this;
}
@ -675,7 +675,7 @@ public class Properties implements Cloneable, Serializable {
* @param decimalPatternMatchRequired true to set an error if decimal is not present
* @return The property bag, for chaining.
*/
public Properties setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired) {
public DecimalFormatProperties setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired) {
this.decimalPatternMatchRequired = decimalPatternMatchRequired;
return this;
}
@ -688,7 +688,7 @@ public class Properties implements Cloneable, Serializable {
* @param decimalSeparatorAlwaysShown Whether to show the decimal point when it is optional.
* @return The property bag, for chaining.
*/
public Properties setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal) {
public DecimalFormatProperties setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal) {
this.decimalSeparatorAlwaysShown = alwaysShowDecimal;
return this;
}
@ -701,7 +701,7 @@ public class Properties implements Cloneable, Serializable {
* @param exponentSignAlwaysShown Whether to show the plus sign in positive exponents.
* @return The property bag, for chaining.
*/
public Properties setExponentSignAlwaysShown(boolean exponentSignAlwaysShown) {
public DecimalFormatProperties setExponentSignAlwaysShown(boolean exponentSignAlwaysShown) {
this.exponentSignAlwaysShown = exponentSignAlwaysShown;
return this;
}
@ -721,7 +721,7 @@ public class Properties implements Cloneable, Serializable {
* @see #setPadPosition
* @see #setPadString
*/
public Properties setFormatWidth(int paddingWidth) {
public DecimalFormatProperties setFormatWidth(int paddingWidth) {
this.formatWidth = paddingWidth;
return this;
}
@ -734,7 +734,7 @@ public class Properties implements Cloneable, Serializable {
* @param groupingSize The primary grouping size.
* @return The property bag, for chaining.
*/
public Properties setGroupingSize(int groupingSize) {
public DecimalFormatProperties setGroupingSize(int groupingSize) {
this.groupingSize = groupingSize;
return this;
}
@ -747,7 +747,7 @@ public class Properties implements Cloneable, Serializable {
* @return The property bag, for chaining.
* @see #setMultiplier
*/
public Properties setMagnitudeMultiplier(int magnitudeMultiplier) {
public DecimalFormatProperties setMagnitudeMultiplier(int magnitudeMultiplier) {
this.magnitudeMultiplier = magnitudeMultiplier;
return this;
}
@ -761,7 +761,7 @@ public class Properties implements Cloneable, Serializable {
* @see MathContext
* @see #setRoundingMode
*/
public Properties setMathContext(MathContext mathContext) {
public DecimalFormatProperties setMathContext(MathContext mathContext) {
this.mathContext = mathContext;
return this;
}
@ -777,7 +777,7 @@ public class Properties implements Cloneable, Serializable {
* @param maximumFractionDigits The maximum number of fraction digits to output.
* @return The property bag, for chaining.
*/
public Properties setMaximumFractionDigits(int maximumFractionDigits) {
public DecimalFormatProperties setMaximumFractionDigits(int maximumFractionDigits) {
this.maximumFractionDigits = maximumFractionDigits;
return this;
}
@ -792,7 +792,7 @@ public class Properties implements Cloneable, Serializable {
* @param maximumIntegerDigits The maximum number of integer digits to output.
* @return The property bag, for chaining.
*/
public Properties setMaximumIntegerDigits(int maximumIntegerDigits) {
public DecimalFormatProperties setMaximumIntegerDigits(int maximumIntegerDigits) {
this.maximumIntegerDigits = maximumIntegerDigits;
return this;
}
@ -816,7 +816,7 @@ public class Properties implements Cloneable, Serializable {
* @param maximumSignificantDigits The maximum number of significant digits to display.
* @return The property bag, for chaining.
*/
public Properties setMaximumSignificantDigits(int maximumSignificantDigits) {
public DecimalFormatProperties setMaximumSignificantDigits(int maximumSignificantDigits) {
this.maximumSignificantDigits = maximumSignificantDigits;
return this;
}
@ -829,7 +829,7 @@ public class Properties implements Cloneable, Serializable {
* @param minimumExponentDigits The minimum number of digits to display in the exponent field.
* @return The property bag, for chaining.
*/
public Properties setMinimumExponentDigits(int exponentDigits) {
public DecimalFormatProperties setMinimumExponentDigits(int exponentDigits) {
this.minimumExponentDigits = exponentDigits;
return this;
}
@ -843,7 +843,7 @@ public class Properties implements Cloneable, Serializable {
* @param minimumFractionDigits The minimum number of fraction digits to output.
* @return The property bag, for chaining.
*/
public Properties setMinimumFractionDigits(int minimumFractionDigits) {
public DecimalFormatProperties setMinimumFractionDigits(int minimumFractionDigits) {
this.minimumFractionDigits = minimumFractionDigits;
return this;
}
@ -858,7 +858,7 @@ public class Properties implements Cloneable, Serializable {
* enabling grouping.
* @return The property bag, for chaining.
*/
public Properties setMinimumGroupingDigits(int minimumGroupingDigits) {
public DecimalFormatProperties setMinimumGroupingDigits(int minimumGroupingDigits) {
this.minimumGroupingDigits = minimumGroupingDigits;
return this;
}
@ -872,7 +872,7 @@ public class Properties implements Cloneable, Serializable {
* @param minimumIntegerDigits The minimum number of integer digits to output.
* @return The property bag, for chaining.
*/
public Properties setMinimumIntegerDigits(int minimumIntegerDigits) {
public DecimalFormatProperties setMinimumIntegerDigits(int minimumIntegerDigits) {
this.minimumIntegerDigits = minimumIntegerDigits;
return this;
}
@ -897,7 +897,7 @@ public class Properties implements Cloneable, Serializable {
* @param minimumSignificantDigits The minimum number of significant digits to display.
* @return The property bag, for chaining.
*/
public Properties setMinimumSignificantDigits(int minimumSignificantDigits) {
public DecimalFormatProperties setMinimumSignificantDigits(int minimumSignificantDigits) {
this.minimumSignificantDigits = minimumSignificantDigits;
return this;
}
@ -909,7 +909,7 @@ public class Properties implements Cloneable, Serializable {
* @return The property bag, for chaining.
* @see #setMagnitudeMultiplier
*/
public Properties setMultiplier(BigDecimal multiplier) {
public DecimalFormatProperties setMultiplier(BigDecimal multiplier) {
this.multiplier = multiplier;
return this;
}
@ -927,7 +927,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setNegativePrefixPattern
*/
public Properties setNegativePrefix(String negativePrefix) {
public DecimalFormatProperties setNegativePrefix(String negativePrefix) {
this.negativePrefix = negativePrefix;
return this;
}
@ -944,7 +944,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setNegativePrefix
*/
public Properties setNegativePrefixPattern(String negativePrefixPattern) {
public DecimalFormatProperties setNegativePrefixPattern(String negativePrefixPattern) {
this.negativePrefixPattern = negativePrefixPattern;
return this;
}
@ -963,7 +963,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setNegativeSuffixPattern
*/
public Properties setNegativeSuffix(String negativeSuffix) {
public DecimalFormatProperties setNegativeSuffix(String negativeSuffix) {
this.negativeSuffix = negativeSuffix;
return this;
}
@ -980,7 +980,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setNegativeSuffix
*/
public Properties setNegativeSuffixPattern(String negativeSuffixPattern) {
public DecimalFormatProperties setNegativeSuffixPattern(String negativeSuffixPattern) {
this.negativeSuffixPattern = negativeSuffixPattern;
return this;
}
@ -995,7 +995,7 @@ public class Properties implements Cloneable, Serializable {
* @return The property bag, for chaining.
* @see #setFormatWidth
*/
public Properties setPadPosition(PadPosition paddingLocation) {
public DecimalFormatProperties setPadPosition(PadPosition paddingLocation) {
this.padPosition = paddingLocation;
return this;
}
@ -1010,7 +1010,7 @@ public class Properties implements Cloneable, Serializable {
* @return The property bag, for chaining.
* @see #setFormatWidth
*/
public Properties setPadString(String paddingString) {
public DecimalFormatProperties setPadString(String paddingString) {
this.padString = paddingString;
return this;
}
@ -1027,7 +1027,7 @@ public class Properties implements Cloneable, Serializable {
* @param parseCaseSensitive true to be case-sensitive when parsing; false to allow any case.
* @return The property bag, for chaining.
*/
public Properties setParseCaseSensitive(boolean parseCaseSensitive) {
public DecimalFormatProperties setParseCaseSensitive(boolean parseCaseSensitive) {
this.parseCaseSensitive = parseCaseSensitive;
return this;
}
@ -1052,7 +1052,7 @@ public class Properties implements Cloneable, Serializable {
* @param parseGroupingMode The {@link GroupingMode} to use; either DEFAULT or RESTRICTED.
* @return The property bag, for chaining.
*/
public Properties setParseGroupingMode(GroupingMode parseGroupingMode) {
public DecimalFormatProperties setParseGroupingMode(GroupingMode parseGroupingMode) {
this.parseGroupingMode = parseGroupingMode;
return this;
}
@ -1065,7 +1065,7 @@ public class Properties implements Cloneable, Serializable {
* fraction parts
* @return The property bag, for chaining.
*/
public Properties setParseIntegerOnly(boolean parseIntegerOnly) {
public DecimalFormatProperties setParseIntegerOnly(boolean parseIntegerOnly) {
this.parseIntegerOnly = parseIntegerOnly;
return this;
}
@ -1077,7 +1077,7 @@ public class Properties implements Cloneable, Serializable {
* @param parseMode Either {@link ParseMode#LENIENT} or {@link ParseMode#STRICT}.
* @return The property bag, for chaining.
*/
public Properties setParseMode(ParseMode parseMode) {
public DecimalFormatProperties setParseMode(ParseMode parseMode) {
this.parseMode = parseMode;
return this;
}
@ -1089,7 +1089,7 @@ public class Properties implements Cloneable, Serializable {
* @param parseIgnoreExponent true to ignore exponents; false to parse them.
* @return The property bag, for chaining.
*/
public Properties setParseNoExponent(boolean parseNoExponent) {
public DecimalFormatProperties setParseNoExponent(boolean parseNoExponent) {
this.parseNoExponent = parseNoExponent;
return this;
}
@ -1102,7 +1102,7 @@ public class Properties implements Cloneable, Serializable {
* BigInteger when possible.
* @return The property bag, for chaining.
*/
public Properties setParseToBigDecimal(boolean parseToBigDecimal) {
public DecimalFormatProperties setParseToBigDecimal(boolean parseToBigDecimal) {
this.parseToBigDecimal = parseToBigDecimal;
return this;
}
@ -1113,7 +1113,7 @@ public class Properties implements Cloneable, Serializable {
* @param pluralRules The object to reference.
* @return The property bag, for chaining.
*/
public Properties setPluralRules(PluralRules pluralRules) {
public DecimalFormatProperties setPluralRules(PluralRules pluralRules) {
this.pluralRules = pluralRules;
return this;
}
@ -1130,7 +1130,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setPositivePrefixPattern
*/
public Properties setPositivePrefix(String positivePrefix) {
public DecimalFormatProperties setPositivePrefix(String positivePrefix) {
this.positivePrefix = positivePrefix;
return this;
}
@ -1147,7 +1147,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setPositivePrefix
*/
public Properties setPositivePrefixPattern(String positivePrefixPattern) {
public DecimalFormatProperties setPositivePrefixPattern(String positivePrefixPattern) {
this.positivePrefixPattern = positivePrefixPattern;
return this;
}
@ -1164,7 +1164,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setPositiveSuffixPattern
*/
public Properties setPositiveSuffix(String positiveSuffix) {
public DecimalFormatProperties setPositiveSuffix(String positiveSuffix) {
this.positiveSuffix = positiveSuffix;
return this;
}
@ -1181,7 +1181,7 @@ public class Properties implements Cloneable, Serializable {
* @see PositiveNegativeAffixFormat
* @see #setPositiveSuffix
*/
public Properties setPositiveSuffixPattern(String positiveSuffixPattern) {
public DecimalFormatProperties setPositiveSuffixPattern(String positiveSuffixPattern) {
this.positiveSuffixPattern = positiveSuffixPattern;
return this;
}
@ -1201,7 +1201,7 @@ public class Properties implements Cloneable, Serializable {
* @param roundingIncrement The interval to which to round.
* @return The property bag, for chaining.
*/
public Properties setRoundingIncrement(BigDecimal roundingIncrement) {
public DecimalFormatProperties setRoundingIncrement(BigDecimal roundingIncrement) {
this.roundingIncrement = roundingIncrement;
return this;
}
@ -1218,7 +1218,7 @@ public class Properties implements Cloneable, Serializable {
* @see RoundingMode
* @see #setMathContext
*/
public Properties setRoundingMode(RoundingMode roundingMode) {
public DecimalFormatProperties setRoundingMode(RoundingMode roundingMode) {
this.roundingMode = roundingMode;
return this;
}
@ -1234,7 +1234,7 @@ public class Properties implements Cloneable, Serializable {
* @param secondaryGroupingSize The secondary grouping size.
* @return The property bag, for chaining.
*/
public Properties setSecondaryGroupingSize(int secondaryGroupingSize) {
public DecimalFormatProperties setSecondaryGroupingSize(int secondaryGroupingSize) {
this.secondaryGroupingSize = secondaryGroupingSize;
return this;
}
@ -1255,7 +1255,7 @@ public class Properties implements Cloneable, Serializable {
* @param plusSignAlwaysShown Whether positive numbers should display a plus sign.
* @return The property bag, for chaining.
*/
public Properties setSignAlwaysShown(boolean signAlwaysShown) {
public DecimalFormatProperties setSignAlwaysShown(boolean signAlwaysShown) {
this.signAlwaysShown = signAlwaysShown;
return this;
}
@ -1274,7 +1274,7 @@ public class Properties implements Cloneable, Serializable {
* surrounded by &lt;Properties&gt;.
*/
public void toStringBare(StringBuilder result) {
Field[] fields = Properties.class.getDeclaredFields();
Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
for (Field field : fields) {
Object myValue, defaultValue;
try {
@ -1309,7 +1309,7 @@ public class Properties implements Cloneable, Serializable {
ArrayList<Field> fieldsToSerialize = new ArrayList<Field>();
ArrayList<Object> valuesToSerialize = new ArrayList<Object>();
Field[] fields = Properties.class.getDeclaredFields();
Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers())) {
continue;

View file

@ -22,9 +22,9 @@ import com.ibm.icu.text.UFieldPosition;
* <p>TODO: Should I change this to an abstract class so that logic for min/max digits doesn't need
* to be copied to every implementation?
*/
public interface FormatQuantity extends PluralRules.IFixedDecimal {
public interface DecimalQuantity extends PluralRules.IFixedDecimal {
/**
* Sets the minimum and maximum integer digits that this {@link FormatQuantity} should generate.
* Sets the minimum and maximum integer digits that this {@link DecimalQuantity} should generate.
* This method does not perform rounding.
*
* @param minInt The minimum number of integer digits.
@ -33,7 +33,7 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal {
public void setIntegerLength(int minInt, int maxInt);
/**
* Sets the minimum and maximum fraction digits that this {@link FormatQuantity} should generate.
* Sets the minimum and maximum fraction digits that this {@link DecimalQuantity} should generate.
* This method does not perform rounding.
*
* @param minFrac The minimum number of fraction digits.
@ -64,7 +64,7 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal {
/**
* Rounds the number to an infinite number of decimal points. This has no effect except for
* forcing the double in {@link FormatQuantityBCD} to adopt its exact representation.
* forcing the double in {@link DecimalQuantity_AbstractBCD} to adopt its exact representation.
*/
public void roundToInfinity();
@ -89,21 +89,21 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal {
*/
public int getMagnitude() throws ArithmeticException;
/** @return Whether the value represented by this {@link FormatQuantity} is zero. */
/** @return Whether the value represented by this {@link DecimalQuantity} is zero. */
public boolean isZero();
/** @return Whether the value represented by this {@link FormatQuantity} is less than zero. */
/** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
public boolean isNegative();
/** @return Whether the value represented by this {@link FormatQuantity} is infinite. */
/** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
@Override
public boolean isInfinite();
/** @return Whether the value represented by this {@link FormatQuantity} is not a number. */
/** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */
@Override
public boolean isNaN();
/** @return The value contained in this {@link FormatQuantity} approximated as a double. */
/** @return The value contained in this {@link DecimalQuantity} approximated as a double. */
public double toDouble();
public BigDecimal toBigDecimal();
@ -112,7 +112,7 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal {
public int maxRepresentableDigits();
// TODO: Should this method be removed, since FormatQuantity implements IFixedDecimal now?
// TODO: Should this method be removed, since DecimalQuantity implements IFixedDecimal now?
/**
* Computes the plural form for this number based on the specified set of rules.
*
@ -182,9 +182,9 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal {
*
* @return A copy of this instance which can be mutated without affecting this instance.
*/
public FormatQuantity createCopy();
public DecimalQuantity createCopy();
public void copyFrom(FormatQuantity other);
public void copyFrom(DecimalQuantity other);
/** This method is for internal testing only. */
public long getPositionFingerprint();

View file

@ -5,7 +5,7 @@ package com.ibm.icu.impl.number;
import java.math.BigDecimal;
import java.math.BigInteger;
public final class FormatQuantity2 extends FormatQuantityBCD {
public final class DecimalQuantity_64BitBCD extends DecimalQuantity_AbstractBCD {
/**
* The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map
@ -21,27 +21,27 @@ public final class FormatQuantity2 extends FormatQuantityBCD {
return 16;
}
public FormatQuantity2(long input) {
public DecimalQuantity_64BitBCD(long input) {
setToLong(input);
}
public FormatQuantity2(int input) {
public DecimalQuantity_64BitBCD(int input) {
setToInt(input);
}
public FormatQuantity2(double input) {
public DecimalQuantity_64BitBCD(double input) {
setToDouble(input);
}
public FormatQuantity2(BigInteger input) {
public DecimalQuantity_64BitBCD(BigInteger input) {
setToBigInteger(input);
}
public FormatQuantity2(BigDecimal input) {
public DecimalQuantity_64BitBCD(BigDecimal input) {
setToBigDecimal(input);
}
public FormatQuantity2(FormatQuantity2 other) {
public DecimalQuantity_64BitBCD(DecimalQuantity_64BitBCD other) {
copyFrom(other);
}
@ -157,15 +157,15 @@ public final class FormatQuantity2 extends FormatQuantityBCD {
}
@Override
protected void copyBcdFrom(FormatQuantity _other) {
FormatQuantity2 other = (FormatQuantity2) _other;
protected void copyBcdFrom(DecimalQuantity _other) {
DecimalQuantity_64BitBCD other = (DecimalQuantity_64BitBCD) _other;
bcd = other.bcd;
}
@Override
public String toString() {
return String.format(
"<FormatQuantity2 %s:%d:%d:%s %016XE%d>",
"<DecimalQuantity2 %s:%d:%d:%s %016XE%d>",
(lOptPos > 1000 ? "max" : String.valueOf(lOptPos)),
lReqPos,
rReqPos,

View file

@ -15,9 +15,9 @@ import com.ibm.icu.text.UFieldPosition;
/**
* Represents numbers and digit display properties using Binary Coded Decimal (BCD).
*
* @implements {@link FormatQuantity}
* @implements {@link DecimalQuantity}
*/
public abstract class FormatQuantityBCD implements FormatQuantity {
public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity {
/**
* The power of ten corresponding to the least significant digit in the BCD. For example, if this
@ -51,10 +51,10 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
protected static final int NAN_FLAG = 4;
// The following three fields relate to the double-to-ascii fast path algorithm.
// When a double is given to FormatQuantityBCD, it is converted to using a fast algorithm. The
// When a double is given to DecimalQuantityBCD, it is converted to using a fast algorithm. The
// fast algorithm guarantees correctness to only the first ~12 digits of the double. The process
// of rounding the number ensures that the converted digits are correct, falling back to a slow-
// path algorithm if required. Therefore, if a FormatQuantity is constructed from a double, it
// path algorithm if required. Therefore, if a DecimalQuantity is constructed from a double, it
// is *required* that roundToMagnitude(), roundToIncrement(), or roundToInfinity() is called. If
// you don't round, assertions will fail in certain other methods if you try calling them.
@ -108,9 +108,9 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
protected int rOptPos = Integer.MIN_VALUE;
@Override
public void copyFrom(FormatQuantity _other) {
public void copyFrom(DecimalQuantity _other) {
copyBcdFrom(_other);
FormatQuantityBCD other = (FormatQuantityBCD) _other;
DecimalQuantity_AbstractBCD other = (DecimalQuantity_AbstractBCD) _other;
lOptPos = other.lOptPos;
lReqPos = other.lReqPos;
rReqPos = other.rReqPos;
@ -123,7 +123,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
isApproximate = other.isApproximate;
}
public FormatQuantityBCD clear() {
public DecimalQuantity_AbstractBCD clear() {
lOptPos = Integer.MAX_VALUE;
lReqPos = 0;
rReqPos = 0;
@ -135,7 +135,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
@Override
public void setIntegerLength(int minInt, int maxInt) {
// Validation should happen outside of FormatQuantity, e.g., in the Rounder class.
// Validation should happen outside of DecimalQuantity, e.g., in the Rounder class.
assert minInt >= 0;
assert maxInt >= minInt;
@ -147,7 +147,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
@Override
public void setFractionLength(int minFrac, int maxFrac) {
// Validation should happen outside of FormatQuantity, e.g., in the Rounder class.
// Validation should happen outside of DecimalQuantity, e.g., in the Rounder class.
assert minFrac >= 0;
assert maxFrac >= minFrac;
@ -311,13 +311,13 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
}
@Override
public FormatQuantity createCopy() {
if (this instanceof FormatQuantity2) {
return new FormatQuantity2((FormatQuantity2) this);
} else if (this instanceof FormatQuantity3) {
return new FormatQuantity3((FormatQuantity3) this);
} else if (this instanceof FormatQuantity4) {
return new FormatQuantity4((FormatQuantity4) this);
public DecimalQuantity createCopy() {
if (this instanceof DecimalQuantity_64BitBCD) {
return new DecimalQuantity_64BitBCD((DecimalQuantity_64BitBCD) this);
} else if (this instanceof DecimalQuantity_ByteArrayBCD) {
return new DecimalQuantity_ByteArrayBCD((DecimalQuantity_ByteArrayBCD) this);
} else if (this instanceof DecimalQuantity_DualStorageBCD) {
return new DecimalQuantity_DualStorageBCD((DecimalQuantity_DualStorageBCD) this);
} else {
throw new IllegalArgumentException("Don't know how to copy " + this.getClass());
}
@ -501,7 +501,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
}
/**
* Whether this {@link FormatQuantity4} has been explicitly converted to an exact double. true if
* Whether this {@link DecimalQuantity_DualStorageBCD} has been explicitly converted to an exact double. true if
* backed by a double that was explicitly converted via convertToAccurateDouble; false otherwise.
* Used for testing.
*
@ -795,7 +795,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
/**
* Appends a digit, optionally with one or more leading zeros, to the end of the value represented
* by this FormatQuantity.
* by this DecimalQuantity.
*
* <p>The primary use of this method is to construct numbers during a parsing loop. It allows
* parsing to take advantage of the digit list infrastructure primarily designed for formatting.
@ -909,7 +909,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
*/
protected abstract BigDecimal bcdToBigDecimal();
protected abstract void copyBcdFrom(FormatQuantity _other);
protected abstract void copyBcdFrom(DecimalQuantity _other);
/**
* Removes trailing zeros from the BCD (adjusting the scale as required) and then computes the

View file

@ -5,7 +5,7 @@ package com.ibm.icu.impl.number;
import java.math.BigDecimal;
import java.math.BigInteger;
public final class FormatQuantity3 extends FormatQuantityBCD {
public final class DecimalQuantity_ByteArrayBCD extends DecimalQuantity_AbstractBCD {
/**
* The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map
@ -21,27 +21,27 @@ public final class FormatQuantity3 extends FormatQuantityBCD {
return Integer.MAX_VALUE;
}
public FormatQuantity3(long input) {
public DecimalQuantity_ByteArrayBCD(long input) {
setToLong(input);
}
public FormatQuantity3(int input) {
public DecimalQuantity_ByteArrayBCD(int input) {
setToInt(input);
}
public FormatQuantity3(double input) {
public DecimalQuantity_ByteArrayBCD(double input) {
setToDouble(input);
}
public FormatQuantity3(BigInteger input) {
public DecimalQuantity_ByteArrayBCD(BigInteger input) {
setToBigInteger(input);
}
public FormatQuantity3(BigDecimal input) {
public DecimalQuantity_ByteArrayBCD(BigDecimal input) {
setToBigDecimal(input);
}
public FormatQuantity3(FormatQuantity3 other) {
public DecimalQuantity_ByteArrayBCD(DecimalQuantity_ByteArrayBCD other) {
copyFrom(other);
}
@ -201,8 +201,8 @@ public final class FormatQuantity3 extends FormatQuantityBCD {
}
@Override
protected void copyBcdFrom(FormatQuantity _other) {
FormatQuantity3 other = (FormatQuantity3) _other;
protected void copyBcdFrom(DecimalQuantity _other) {
DecimalQuantity_ByteArrayBCD other = (DecimalQuantity_ByteArrayBCD) _other;
System.arraycopy(other.bcd, 0, bcd, 0, bcd.length);
}
@ -213,7 +213,7 @@ public final class FormatQuantity3 extends FormatQuantityBCD {
sb.append(bcd[i]);
}
return String.format(
"<FormatQuantity3 %s:%d:%d:%s %s%s%d>",
"<DecimalQuantity3 %s:%d:%d:%s %s%s%d>",
(lOptPos > 1000 ? "max" : String.valueOf(lOptPos)),
lReqPos,
rReqPos,

View file

@ -5,7 +5,11 @@ package com.ibm.icu.impl.number;
import java.math.BigDecimal;
import java.math.BigInteger;
public final class FormatQuantity4 extends FormatQuantityBCD {
/**
* A DecimalQuantity with internal storage as a 64-bit BCD, with fallback to a byte array
* for numbers that don't fit into the standard BCD.
*/
public final class DecimalQuantity_DualStorageBCD extends DecimalQuantity_AbstractBCD {
/**
* The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map
@ -25,35 +29,35 @@ public final class FormatQuantity4 extends FormatQuantityBCD {
return Integer.MAX_VALUE;
}
public FormatQuantity4() {
public DecimalQuantity_DualStorageBCD() {
setBcdToZero();
}
public FormatQuantity4(long input) {
public DecimalQuantity_DualStorageBCD(long input) {
setToLong(input);
}
public FormatQuantity4(int input) {
public DecimalQuantity_DualStorageBCD(int input) {
setToInt(input);
}
public FormatQuantity4(double input) {
public DecimalQuantity_DualStorageBCD(double input) {
setToDouble(input);
}
public FormatQuantity4(BigInteger input) {
public DecimalQuantity_DualStorageBCD(BigInteger input) {
setToBigInteger(input);
}
public FormatQuantity4(BigDecimal input) {
public DecimalQuantity_DualStorageBCD(BigDecimal input) {
setToBigDecimal(input);
}
public FormatQuantity4(FormatQuantity4 other) {
public DecimalQuantity_DualStorageBCD(DecimalQuantity_DualStorageBCD other) {
copyFrom(other);
}
public FormatQuantity4(Number number) {
public DecimalQuantity_DualStorageBCD(Number number) {
if (number instanceof Long) {
setToLong(number.longValue());
} else if (number instanceof Integer) {
@ -317,8 +321,8 @@ public final class FormatQuantity4 extends FormatQuantityBCD {
}
@Override
protected void copyBcdFrom(FormatQuantity _other) {
FormatQuantity4 other = (FormatQuantity4) _other;
protected void copyBcdFrom(DecimalQuantity _other) {
DecimalQuantity_DualStorageBCD other = (DecimalQuantity_DualStorageBCD) _other;
if (other.usingBytes) {
usingBytes = true;
ensureCapacity(other.precision);
@ -376,7 +380,7 @@ public final class FormatQuantity4 extends FormatQuantityBCD {
}
/**
* Checks whether this {@link FormatQuantity4} is using its internal byte array storage mechanism.
* Checks whether this {@link DecimalQuantity_DualStorageBCD} is using its internal byte array storage mechanism.
*
* @return true if an internal byte array is being used; false if a long is being used.
* @internal
@ -398,7 +402,7 @@ public final class FormatQuantity4 extends FormatQuantityBCD {
sb.append(Long.toHexString(bcdLong));
}
return String.format(
"<FormatQuantity4 %s:%d:%d:%s %s %s%s%d>",
"<DecimalQuantity4 %s:%d:%d:%s %s %s%s%d>",
(lOptPos > 1000 ? "max" : String.valueOf(lOptPos)),
lReqPos,
rReqPos,

View file

@ -13,14 +13,14 @@ import com.ibm.icu.text.PluralRules.Operand;
import com.ibm.icu.text.UFieldPosition;
/**
* This is an older implementation of FormatQuantity. A newer, faster implementation is
* FormatQuantity2. I kept this implementation around because it was useful for testing purposes
* This is an older implementation of DecimalQuantity. A newer, faster implementation is
* DecimalQuantity2. I kept this implementation around because it was useful for testing purposes
* (being able to compare the output of one implementation with the other).
*
* <p>This class is NOT IMMUTABLE and NOT THREAD SAFE and is intended to be used by a single thread
* to format a number through a formatter, which is thread-safe.
*/
public class FormatQuantity1 implements FormatQuantity {
public class DecimalQuantity_SimpleStorage implements DecimalQuantity {
// Four positions: left optional '(', left required '[', right required ']', right optional ')'.
// These four positions determine which digits are displayed in the output string. They do NOT
// affect rounding. These positions are internal-only and can be specified only by the public
@ -98,7 +98,7 @@ public class FormatQuantity1 implements FormatQuantity {
return Integer.MAX_VALUE;
}
public FormatQuantity1(long input) {
public DecimalQuantity_SimpleStorage(long input) {
if (input < 0) {
setNegative(true);
input *= -1;
@ -111,13 +111,13 @@ public class FormatQuantity1 implements FormatQuantity {
}
/**
* Creates a FormatQuantity from the given double value. Internally attempts several strategies
* Creates a DecimalQuantity from the given double value. Internally attempts several strategies
* for converting the double to an exact representation, falling back on a BigDecimal if it fails
* to do so.
*
* @param input The double to represent by this FormatQuantity.
* @param input The double to represent by this DecimalQuantity.
*/
public FormatQuantity1(double input) {
public DecimalQuantity_SimpleStorage(double input) {
if (input < 0) {
setNegative(true);
input *= -1;
@ -191,7 +191,7 @@ public class FormatQuantity1 implements FormatQuantity {
static final double LOG_2_OF_TEN = 3.32192809489;
public FormatQuantity1(double input, boolean fast) {
public DecimalQuantity_SimpleStorage(double input, boolean fast) {
if (input < 0) {
setNegative(true);
input *= -1;
@ -230,11 +230,11 @@ public class FormatQuantity1 implements FormatQuantity {
}
}
public FormatQuantity1(BigDecimal decimal) {
public DecimalQuantity_SimpleStorage(BigDecimal decimal) {
setToBigDecimal(decimal);
}
public FormatQuantity1(FormatQuantity1 other) {
public DecimalQuantity_SimpleStorage(DecimalQuantity_SimpleStorage other) {
copyFrom(other);
}
@ -254,20 +254,20 @@ public class FormatQuantity1 implements FormatQuantity {
}
@Override
public FormatQuantity1 createCopy() {
return new FormatQuantity1(this);
public DecimalQuantity_SimpleStorage createCopy() {
return new DecimalQuantity_SimpleStorage(this);
}
/**
* Make the internal state of this FormatQuantity equal to another FormatQuantity.
* Make the internal state of this DecimalQuantity equal to another DecimalQuantity.
*
* @param other The template FormatQuantity. All properties from this FormatQuantity will be
* copied into this FormatQuantity.
* @param other The template DecimalQuantity. All properties from this DecimalQuantity will be
* copied into this DecimalQuantity.
*/
@Override
public void copyFrom(FormatQuantity other) {
public void copyFrom(DecimalQuantity other) {
// TODO: Check before casting
FormatQuantity1 _other = (FormatQuantity1) other;
DecimalQuantity_SimpleStorage _other = (DecimalQuantity_SimpleStorage) other;
lOptPos = _other.lOptPos;
lReqPos = _other.lReqPos;
rReqPos = _other.rReqPos;
@ -457,7 +457,7 @@ public class FormatQuantity1 implements FormatQuantity {
}
}
/** @return The power of ten of the highest digit represented by this FormatQuantity */
/** @return The power of ten of the highest digit represented by this DecimalQuantity */
@Override
public int getMagnitude() throws ArithmeticException {
int scale = (primary == -1) ? scaleBigDecimal(fallback) : primaryScale;
@ -470,8 +470,8 @@ public class FormatQuantity1 implements FormatQuantity {
}
/**
* Changes the magnitude of this FormatQuantity. If the indices of the represented digits had been
* previously specified, those indices are moved relative to the FormatQuantity.
* Changes the magnitude of this DecimalQuantity. If the indices of the represented digits had been
* previously specified, those indices are moved relative to the DecimalQuantity.
*
* <p>This method does NOT perform rounding.
*
@ -496,7 +496,7 @@ public class FormatQuantity1 implements FormatQuantity {
return a + b;
}
/** @return If the number represented by this FormatQuantity is less than zero */
/** @return If the number represented by this DecimalQuantity is less than zero */
@Override
public boolean isNegative() {
return (flags & NEGATIVE_FLAG) != 0;
@ -525,7 +525,7 @@ public class FormatQuantity1 implements FormatQuantity {
}
/**
* Returns a representation of this FormatQuantity as a double, with possible loss of information.
* Returns a representation of this DecimalQuantity as a double, with possible loss of information.
*/
@Override
public double toDouble() {
@ -686,7 +686,7 @@ public class FormatQuantity1 implements FormatQuantity {
private int fractionCount() {
// TODO: This is temporary.
FormatQuantity1 copy = new FormatQuantity1(this);
DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this);
int fractionCount = 0;
while (copy.hasNextFraction()) {
copy.nextFraction();
@ -718,7 +718,7 @@ public class FormatQuantity1 implements FormatQuantity {
@Override
public byte getDigit(int magnitude) {
// TODO: This is temporary.
FormatQuantity1 copy = new FormatQuantity1(this);
DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this);
if (magnitude < 0) {
for (int p = -1; p > magnitude; p--) {
copy.nextFraction();
@ -817,7 +817,7 @@ public class FormatQuantity1 implements FormatQuantity {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("<FormatQuantity1 ");
sb.append("<DecimalQuantity1 ");
if (primary == -1) {
sb.append(lOptPos > 1000 ? "max" : lOptPos);
sb.append(":");

View file

@ -2,7 +2,7 @@
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.impl.number;
import newapi.MutablePatternModifier;
import newapi.impl.MutablePatternModifier;
/**
* A Modifier is an object that can be passed through the formatting pipeline until it is finally applied to the string

View file

@ -113,7 +113,7 @@ public class Parse {
}
/**
* @see Parse#parse(String, ParsePosition, ParseMode, boolean, boolean, Properties,
* @see Parse#parse(String, ParsePosition, ParseMode, boolean, boolean, DecimalFormatProperties,
* DecimalFormatSymbols)
*/
private static enum StateName {
@ -203,7 +203,7 @@ public class Parse {
int score;
// Numerical value:
FormatQuantity4 fq = new FormatQuantity4();
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
int numDigits;
int trailingZeros;
int exponent;
@ -400,7 +400,7 @@ public class Parse {
*
* @return The Number. Never null.
*/
Number toNumber(Properties properties) {
Number toNumber(DecimalFormatProperties properties) {
// Check for NaN, infinity, and -0.0
if (sawNaN) {
return Double.NaN;
@ -470,7 +470,7 @@ public class Parse {
*
* @return The CurrencyAmount. Never null.
*/
public CurrencyAmount toCurrencyAmount(Properties properties) {
public CurrencyAmount toCurrencyAmount(DecimalFormatProperties properties) {
assert isoCode != null;
Number number = toNumber(properties);
Currency currency = Currency.getInstance(isoCode);
@ -495,7 +495,7 @@ public class Parse {
sb.append("{");
sb.append(currentAffixPattern);
sb.append(":");
sb.append(AffixPatternUtils.getOffset(currentStepwiseParserTag) - 1);
sb.append(AffixUtils.getOffset(currentStepwiseParserTag) - 1);
sb.append("}");
}
sb.append(" ");
@ -539,7 +539,7 @@ public class Parse {
int prevLength;
// Properties and Symbols memory:
Properties properties;
DecimalFormatProperties properties;
DecimalFormatSymbols symbols;
ParseMode mode;
boolean caseSensitive;
@ -680,7 +680,7 @@ public class Parse {
static final AffixHolder EMPTY_POSITIVE = new AffixHolder("", "", true, false);
static final AffixHolder EMPTY_NEGATIVE = new AffixHolder("", "", true, true);
static void addToState(ParserState state, Properties properties) {
static void addToState(ParserState state, DecimalFormatProperties properties) {
AffixHolder pp = fromPropertiesPositivePattern(properties);
AffixHolder np = fromPropertiesNegativePattern(properties);
AffixHolder ps = fromPropertiesPositiveString(properties);
@ -691,7 +691,7 @@ public class Parse {
if (ns != null) state.affixHolders.add(ns);
}
static AffixHolder fromPropertiesPositivePattern(Properties properties) {
static AffixHolder fromPropertiesPositivePattern(DecimalFormatProperties properties) {
String ppp = properties.getPositivePrefixPattern();
String psp = properties.getPositiveSuffixPattern();
if (properties.getSignAlwaysShown()) {
@ -699,13 +699,13 @@ public class Parse {
boolean foundSign = false;
String npp = properties.getNegativePrefixPattern();
String nsp = properties.getNegativeSuffixPattern();
if (AffixPatternUtils.containsType(npp, AffixPatternUtils.TYPE_MINUS_SIGN)) {
if (AffixUtils.containsType(npp, AffixUtils.TYPE_MINUS_SIGN)) {
foundSign = true;
ppp = AffixPatternUtils.replaceType(npp, AffixPatternUtils.TYPE_MINUS_SIGN, '+');
ppp = AffixUtils.replaceType(npp, AffixUtils.TYPE_MINUS_SIGN, '+');
}
if (AffixPatternUtils.containsType(nsp, AffixPatternUtils.TYPE_MINUS_SIGN)) {
if (AffixUtils.containsType(nsp, AffixUtils.TYPE_MINUS_SIGN)) {
foundSign = true;
psp = AffixPatternUtils.replaceType(nsp, AffixPatternUtils.TYPE_MINUS_SIGN, '+');
psp = AffixUtils.replaceType(nsp, AffixUtils.TYPE_MINUS_SIGN, '+');
}
if (!foundSign) {
ppp = "+" + ppp;
@ -714,7 +714,7 @@ public class Parse {
return getInstance(ppp, psp, false, false);
}
static AffixHolder fromPropertiesNegativePattern(Properties properties) {
static AffixHolder fromPropertiesNegativePattern(DecimalFormatProperties properties) {
String npp = properties.getNegativePrefixPattern();
String nsp = properties.getNegativeSuffixPattern();
if (npp == null && nsp == null) {
@ -729,14 +729,14 @@ public class Parse {
return getInstance(npp, nsp, false, true);
}
static AffixHolder fromPropertiesPositiveString(Properties properties) {
static AffixHolder fromPropertiesPositiveString(DecimalFormatProperties properties) {
String pp = properties.getPositivePrefix();
String ps = properties.getPositiveSuffix();
if (pp == null && ps == null) return null;
return getInstance(pp, ps, true, false);
}
static AffixHolder fromPropertiesNegativeString(Properties properties) {
static AffixHolder fromPropertiesNegativeString(DecimalFormatProperties properties) {
String np = properties.getNegativePrefix();
String ns = properties.getNegativeSuffix();
if (np == null && ns == null) return null;
@ -826,18 +826,18 @@ public class Parse {
}
}
private static final ThreadLocal<Properties> threadLocalProperties =
new ThreadLocal<Properties>() {
private static final ThreadLocal<DecimalFormatProperties> threadLocalProperties =
new ThreadLocal<DecimalFormatProperties>() {
@Override
protected Properties initialValue() {
return new Properties();
protected DecimalFormatProperties initialValue() {
return new DecimalFormatProperties();
}
};
private void addPattern(String pattern) {
Properties properties = threadLocalProperties.get();
DecimalFormatProperties properties = threadLocalProperties.get();
try {
PatternAndPropertyUtils.parseToExistingProperties(pattern, properties);
PatternStringParser.parseToExistingProperties(pattern, properties);
} catch (IllegalArgumentException e) {
// This should only happen if there is a bug in CLDR data. Fail silently.
}
@ -912,7 +912,7 @@ public class Parse {
0xFE63, 0xFE63, 0xFF0D, 0xFF0D)
.freeze();
public static Number parse(String input, Properties properties, DecimalFormatSymbols symbols) {
public static Number parse(String input, DecimalFormatProperties properties, DecimalFormatSymbols symbols) {
ParsePosition ppos = threadLocalParsePosition.get();
ppos.setIndex(0);
return parse(input, ppos, properties, symbols);
@ -940,19 +940,19 @@ public class Parse {
public static Number parse(
CharSequence input,
ParsePosition ppos,
Properties properties,
DecimalFormatProperties properties,
DecimalFormatSymbols symbols) {
StateItem best = _parse(input, ppos, false, properties, symbols);
return (best == null) ? null : best.toNumber(properties);
}
public static CurrencyAmount parseCurrency(
String input, Properties properties, DecimalFormatSymbols symbols) throws ParseException {
String input, DecimalFormatProperties properties, DecimalFormatSymbols symbols) throws ParseException {
return parseCurrency(input, null, properties, symbols);
}
public static CurrencyAmount parseCurrency(
CharSequence input, ParsePosition ppos, Properties properties, DecimalFormatSymbols symbols)
CharSequence input, ParsePosition ppos, DecimalFormatProperties properties, DecimalFormatSymbols symbols)
throws ParseException {
if (ppos == null) {
ppos = threadLocalParsePosition.get();
@ -967,7 +967,7 @@ public class Parse {
CharSequence input,
ParsePosition ppos,
boolean parseCurrency,
Properties properties,
DecimalFormatProperties properties,
DecimalFormatSymbols symbols) {
if (input == null || ppos == null || properties == null || symbols == null) {
@ -1716,7 +1716,7 @@ public class Parse {
added = acceptString(cp, nextName, null, state, item, str, 0, false);
} else {
added =
acceptAffixPattern(cp, nextName, state, item, str, AffixPatternUtils.nextToken(0, str));
acceptAffixPattern(cp, nextName, state, item, str, AffixUtils.nextToken(0, str));
}
// Record state in the added entries
for (int i = Long.numberOfTrailingZeros(added); (1L << i) <= added; i++) {
@ -1899,27 +1899,27 @@ public class Parse {
if (typeOrCp < 0) {
// Symbol
switch (typeOrCp) {
case AffixPatternUtils.TYPE_MINUS_SIGN:
case AffixUtils.TYPE_MINUS_SIGN:
resolvedMinusSign = true;
break;
case AffixPatternUtils.TYPE_PLUS_SIGN:
case AffixUtils.TYPE_PLUS_SIGN:
resolvedPlusSign = true;
break;
case AffixPatternUtils.TYPE_PERCENT:
case AffixUtils.TYPE_PERCENT:
resolvedStr = state.symbols.getPercentString();
if (resolvedStr.length() != 1 || resolvedStr.charAt(0) != '%') {
resolvedCp = '%'; // accept ASCII percent as well as locale percent
}
break;
case AffixPatternUtils.TYPE_PERMILLE:
case AffixUtils.TYPE_PERMILLE:
resolvedStr = state.symbols.getPerMillString();
if (resolvedStr.length() != 1 || resolvedStr.charAt(0) != '‰') {
resolvedCp = '‰'; // accept ASCII permille as well as locale permille
}
break;
case AffixPatternUtils.TYPE_CURRENCY_SINGLE:
case AffixPatternUtils.TYPE_CURRENCY_DOUBLE:
case AffixPatternUtils.TYPE_CURRENCY_TRIPLE:
case AffixUtils.TYPE_CURRENCY_SINGLE:
case AffixUtils.TYPE_CURRENCY_DOUBLE:
case AffixUtils.TYPE_CURRENCY_TRIPLE:
resolvedCurrency = true;
break;
default:
@ -2094,7 +2094,7 @@ public class Parse {
int typeOrCp =
isString
? Character.codePointAt(str, (int) offsetOrTag)
: AffixPatternUtils.getTypeOrCp(offsetOrTag);
: AffixUtils.getTypeOrCp(offsetOrTag);
if (isIgnorable(typeOrCp, state)) {
// Look for the next nonignorable code point
@ -2107,7 +2107,7 @@ public class Parse {
nextOffsetOrTag =
isString
? nextOffsetOrTag + Character.charCount(nextTypeOrCp)
: AffixPatternUtils.nextToken(nextOffsetOrTag, str);
: AffixUtils.nextToken(nextOffsetOrTag, str);
if (firstOffsetOrTag == 0L) firstOffsetOrTag = nextOffsetOrTag;
if (isString ? nextOffsetOrTag >= str.length() : nextOffsetOrTag < 0) {
// Integer.MIN_VALUE is an invalid value for either a type or a cp;
@ -2118,7 +2118,7 @@ public class Parse {
nextTypeOrCp =
isString
? Character.codePointAt(str, (int) nextOffsetOrTag)
: AffixPatternUtils.getTypeOrCp(nextOffsetOrTag);
: AffixUtils.getTypeOrCp(nextOffsetOrTag);
if (!isIgnorable(nextTypeOrCp, state)) break;
}
@ -2177,7 +2177,7 @@ public class Parse {
nextOffsetOrTag =
isString
? nextOffsetOrTag + Character.charCount(nextTypeOrCp)
: AffixPatternUtils.nextToken(nextOffsetOrTag, str);
: AffixUtils.nextToken(nextOffsetOrTag, str);
if (firstOffsetOrTag == 0L) firstOffsetOrTag = nextOffsetOrTag;
if (isString ? nextOffsetOrTag >= str.length() : nextOffsetOrTag < 0) {
nextTypeOrCp = -1;
@ -2186,7 +2186,7 @@ public class Parse {
nextTypeOrCp =
isString
? Character.codePointAt(str, (int) nextOffsetOrTag)
: AffixPatternUtils.getTypeOrCp(nextOffsetOrTag);
: AffixUtils.getTypeOrCp(nextOffsetOrTag);
if (!isIgnorable(nextTypeOrCp, state)) break;
}

View file

@ -6,20 +6,24 @@ import newapi.impl.AffixPatternProvider;
import newapi.impl.Padder.PadPosition;
/** Implements a recursive descent parser for decimal format patterns. */
public class PatternParser {
public class PatternStringParser {
public static final int IGNORE_ROUNDING_NEVER = 0;
public static final int IGNORE_ROUNDING_IF_CURRENCY = 1;
public static final int IGNORE_ROUNDING_ALWAYS = 2;
/**
* Runs the recursive descent parser on the given pattern string, returning a data structure with raw information
* about the pattern string.
*
* <p>
* To obtain a more useful form of the data, consider using {@link PatternAndPropertyUtils#parse} instead.
* To obtain a more useful form of the data, consider using {@link #parseToProperties} instead.
*
* @param patternString
* The LDML decimal format pattern (Excel-style pattern) to parse.
* @return The results of the parse.
*/
public static ParsedPatternInfo parse(String patternString) {
public static ParsedPatternInfo parseToPatternInfo(String patternString) {
ParserState state = new ParserState(patternString);
ParsedPatternInfo result = new ParsedPatternInfo(patternString);
consumePattern(state, result);
@ -27,9 +31,59 @@ public class PatternParser {
}
/**
* Contains information about
* @author sffc
* Parses a pattern string into a new property bag.
*
* @param pattern
* The pattern string, like "#,##0.00"
* @param ignoreRounding
* Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the
* pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used
* instead. One of {@link PatternStringParser#IGNORE_ROUNDING_ALWAYS},
* {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY}, or
* {@link PatternStringParser#IGNORE_ROUNDING_NEVER}.
* @return A property bag object.
* @throws IllegalArgumentException
* If there is a syntax error in the pattern string.
*/
public static DecimalFormatProperties parseToProperties(String pattern, int ignoreRounding) {
DecimalFormatProperties properties = new DecimalFormatProperties();
parseToExistingPropertiesImpl(pattern, properties, ignoreRounding);
return properties;
}
public static DecimalFormatProperties parseToProperties(String pattern) {
return parseToProperties(pattern, PatternStringParser.IGNORE_ROUNDING_NEVER);
}
/**
* Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string
* will be overwritten with either their default value or with the value coming from the pattern string. Properties
* that cannot be encoded into a pattern string, such as rounding mode, are not modified.
*
* @param pattern
* The pattern string, like "#,##0.00"
* @param properties
* The property bag object to overwrite.
* @param ignoreRounding
* See {@link #parseToProperties(String pattern, int ignoreRounding)}.
* @throws IllegalArgumentException
* If there was a syntax error in the pattern string.
*/
public static void parseToExistingProperties(String pattern, DecimalFormatProperties properties,
int ignoreRounding) {
parseToExistingPropertiesImpl(pattern, properties, ignoreRounding);
}
public static void parseToExistingProperties(String pattern, DecimalFormatProperties properties) {
parseToExistingProperties(pattern, properties, PatternStringParser.IGNORE_ROUNDING_NEVER);
}
/////////////////////////////////////////////////////
/// BEGIN RECURSIVE DESCENT PARSER IMPLEMENTATION ///
/////////////////////////////////////////////////////
/**
* Contains raw information about the parsed decimal format pattern string.
*/
public static class ParsedPatternInfo implements AffixPatternProvider {
public String pattern;
@ -113,7 +167,7 @@ public class PatternParser {
@Override
public boolean containsSymbolType(int type) {
return AffixPatternUtils.containsType(pattern, type);
return AffixUtils.containsType(pattern, type);
}
}
@ -130,7 +184,7 @@ public class PatternParser {
public boolean hasDecimal = false;
public int widthExceptAffixes = 0;
public PadPosition paddingLocation = null;
public FormatQuantity4 rounding = null;
public DecimalQuantity_DualStorageBCD rounding = null;
public boolean exponentHasPlusSign = false;
public int exponentZeros = 0;
public boolean hasPercentSign = false;
@ -353,7 +407,7 @@ public class PatternParser {
result.integerNumerals += 1;
result.integerTotal += 1;
if (state.peek() != '0' && result.rounding == null) {
result.rounding = new FormatQuantity4();
result.rounding = new DecimalQuantity_DualStorageBCD();
}
if (result.rounding != null) {
result.rounding.appendDigit((byte) (state.peek() - '0'), 0, true);
@ -409,7 +463,7 @@ public class PatternParser {
zeroCounter++;
} else {
if (result.rounding == null) {
result.rounding = new FormatQuantity4();
result.rounding = new DecimalQuantity_DualStorageBCD();
}
result.rounding.appendDigit((byte) (state.peek() - '0'), zeroCounter, false);
zeroCounter = 0;
@ -440,4 +494,185 @@ public class PatternParser {
result.widthExceptAffixes++;
}
}
///////////////////////////////////////////////////
/// END RECURSIVE DESCENT PARSER IMPLEMENTATION ///
///////////////////////////////////////////////////
private static void parseToExistingPropertiesImpl(String pattern, DecimalFormatProperties properties, int ignoreRounding) {
if (pattern == null || pattern.length() == 0) {
// Backwards compatibility requires that we reset to the default values.
// TODO: Only overwrite the properties that "saveToProperties" normally touches?
properties.clear();
return;
}
// TODO: Use thread locals here?
ParsedPatternInfo patternInfo = parseToPatternInfo(pattern);
patternInfoToProperties(properties, patternInfo, ignoreRounding);
}
/** Finalizes the temporary data stored in the ParsedPatternInfo to the Properties. */
private static void patternInfoToProperties(DecimalFormatProperties properties, ParsedPatternInfo patternInfo,
int _ignoreRounding) {
// Translate from PatternParseResult to Properties.
// Note that most data from "negative" is ignored per the specification of DecimalFormat.
ParsedSubpatternInfo positive = patternInfo.positive;
ParsedSubpatternInfo negative = patternInfo.negative;
boolean ignoreRounding;
if (_ignoreRounding == PatternStringParser.IGNORE_ROUNDING_NEVER) {
ignoreRounding = false;
} else if (_ignoreRounding == PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY) {
ignoreRounding = positive.hasCurrencySign;
} else {
assert _ignoreRounding == PatternStringParser.IGNORE_ROUNDING_ALWAYS;
ignoreRounding = true;
}
// Grouping settings
short grouping1 = (short) (positive.groupingSizes & 0xffff);
short grouping2 = (short) ((positive.groupingSizes >>> 16) & 0xffff);
short grouping3 = (short) ((positive.groupingSizes >>> 32) & 0xffff);
if (grouping2 != -1) {
properties.setGroupingSize(grouping1);
} else {
properties.setGroupingSize(-1);
}
if (grouping3 != -1) {
properties.setSecondaryGroupingSize(grouping2);
} else {
properties.setSecondaryGroupingSize(-1);
}
// For backwards compatibility, require that the pattern emit at least one min digit.
int minInt, minFrac;
if (positive.integerTotal == 0 && positive.fractionTotal > 0) {
// patterns like ".##"
minInt = 0;
minFrac = Math.max(1, positive.fractionNumerals);
} else if (positive.integerNumerals == 0 && positive.fractionNumerals == 0) {
// patterns like "#.##"
minInt = 1;
minFrac = 0;
} else {
minInt = positive.integerNumerals;
minFrac = positive.fractionNumerals;
}
// Rounding settings
// Don't set basic rounding when there is a currency sign; defer to CurrencyUsage
if (positive.integerAtSigns > 0) {
properties.setMinimumFractionDigits(-1);
properties.setMaximumFractionDigits(-1);
properties.setRoundingIncrement(null);
properties.setMinimumSignificantDigits(positive.integerAtSigns);
properties.setMaximumSignificantDigits(positive.integerAtSigns + positive.integerTrailingHashSigns);
} else if (positive.rounding != null) {
if (!ignoreRounding) {
properties.setMinimumFractionDigits(minFrac);
properties.setMaximumFractionDigits(positive.fractionTotal);
properties.setRoundingIncrement(positive.rounding.toBigDecimal().setScale(positive.fractionNumerals));
} else {
properties.setMinimumFractionDigits(-1);
properties.setMaximumFractionDigits(-1);
properties.setRoundingIncrement(null);
}
properties.setMinimumSignificantDigits(-1);
properties.setMaximumSignificantDigits(-1);
} else {
if (!ignoreRounding) {
properties.setMinimumFractionDigits(minFrac);
properties.setMaximumFractionDigits(positive.fractionTotal);
properties.setRoundingIncrement(null);
} else {
properties.setMinimumFractionDigits(-1);
properties.setMaximumFractionDigits(-1);
properties.setRoundingIncrement(null);
}
properties.setMinimumSignificantDigits(-1);
properties.setMaximumSignificantDigits(-1);
}
// If the pattern ends with a '.' then force the decimal point.
if (positive.hasDecimal && positive.fractionTotal == 0) {
properties.setDecimalSeparatorAlwaysShown(true);
} else {
properties.setDecimalSeparatorAlwaysShown(false);
}
// Scientific notation settings
if (positive.exponentZeros > 0) {
properties.setExponentSignAlwaysShown(positive.exponentHasPlusSign);
properties.setMinimumExponentDigits(positive.exponentZeros);
if (positive.integerAtSigns == 0) {
// patterns without '@' can define max integer digits, used for engineering notation
properties.setMinimumIntegerDigits(positive.integerNumerals);
properties.setMaximumIntegerDigits(positive.integerTotal);
} else {
// patterns with '@' cannot define max integer digits
properties.setMinimumIntegerDigits(1);
properties.setMaximumIntegerDigits(-1);
}
} else {
properties.setExponentSignAlwaysShown(false);
properties.setMinimumExponentDigits(-1);
properties.setMinimumIntegerDigits(minInt);
properties.setMaximumIntegerDigits(-1);
}
// Compute the affix patterns (required for both padding and affixes)
String posPrefix = patternInfo.getString(AffixPatternProvider.Flags.PREFIX);
String posSuffix = patternInfo.getString(0);
// Padding settings
if (positive.paddingEndpoints != 0) {
// The width of the positive prefix and suffix templates are included in the padding
int paddingWidth = positive.widthExceptAffixes + AffixUtils.estimateLength(posPrefix)
+ AffixUtils.estimateLength(posSuffix);
properties.setFormatWidth(paddingWidth);
String rawPaddingString = patternInfo.getString(AffixPatternProvider.Flags.PADDING);
if (rawPaddingString.length() == 1) {
properties.setPadString(rawPaddingString);
} else if (rawPaddingString.length() == 2) {
if (rawPaddingString.charAt(0) == '\'') {
properties.setPadString("'");
} else {
properties.setPadString(rawPaddingString);
}
} else {
properties.setPadString(rawPaddingString.substring(1, rawPaddingString.length() - 1));
}
assert positive.paddingLocation != null;
properties.setPadPosition(positive.paddingLocation);
} else {
properties.setFormatWidth(-1);
properties.setPadString(null);
properties.setPadPosition(null);
}
// Set the affixes
// Always call the setter, even if the prefixes are empty, especially in the case of the
// negative prefix pattern, to prevent default values from overriding the pattern.
properties.setPositivePrefixPattern(posPrefix);
properties.setPositiveSuffixPattern(posSuffix);
if (negative != null) {
properties.setNegativePrefixPattern(patternInfo
.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN | AffixPatternProvider.Flags.PREFIX));
properties.setNegativeSuffixPattern(patternInfo.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN));
} else {
properties.setNegativePrefixPattern(null);
properties.setNegativeSuffixPattern(null);
}
// Set the magnitude multiplier
if (positive.hasPercentSign) {
properties.setMagnitudeMultiplier(2);
} else if (positive.hasPerMilleSign) {
properties.setMagnitudeMultiplier(3);
} else {
properties.setMagnitudeMultiplier(0);
}
}
}

View file

@ -4,67 +4,15 @@ package com.ibm.icu.impl.number;
import java.math.BigDecimal;
import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.PatternParser.ParsedSubpatternInfo;
import com.ibm.icu.text.DecimalFormatSymbols;
import newapi.impl.AffixPatternProvider;
import newapi.impl.Padder;
import newapi.impl.Padder.PadPosition;
/**
* Handles parsing and creation of the compact pattern string representation of a decimal format.
* Assorted utilities relating to decimal formatting pattern strings.
*/
public class PatternAndPropertyUtils {
/**
* Parses a pattern string into a new property bag.
*
* @param pattern
* The pattern string, like "#,##0.00"
* @param ignoreRounding
* Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the
* pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used
* instead. One of {@link #IGNORE_ROUNDING_ALWAYS}, {@link #IGNORE_ROUNDING_IF_CURRENCY}, or
* {@link #IGNORE_ROUNDING_NEVER}.
* @return A property bag object.
* @throws IllegalArgumentException
* If there is a syntax error in the pattern string.
*/
public static Properties parseToProperties(String pattern, int ignoreRounding) {
Properties properties = new Properties();
parse(pattern, properties, ignoreRounding);
return properties;
}
public static Properties parseToProperties(String pattern) {
return parseToProperties(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER);
}
/**
* Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string
* will be overwritten with either their default value or with the value coming from the pattern string. Properties
* that cannot be encoded into a pattern string, such as rounding mode, are not modified.
*
* @param pattern
* The pattern string, like "#,##0.00"
* @param properties
* The property bag object to overwrite.
* @param ignoreRounding
* Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the
* pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used
* instead. One of {@link #IGNORE_ROUNDING_ALWAYS}, {@link #IGNORE_ROUNDING_IF_CURRENCY}, or
* {@link #IGNORE_ROUNDING_NEVER}.
* @throws IllegalArgumentException
* If there was a syntax error in the pattern string.
*/
public static void parseToExistingProperties(String pattern, Properties properties, int ignoreRounding) {
parse(pattern, properties, ignoreRounding);
}
public static void parseToExistingProperties(String pattern, Properties properties) {
parseToExistingProperties(pattern, properties, PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER);
}
public class PatternStringUtils {
/**
* Creates a pattern string from a property bag.
@ -77,7 +25,7 @@ public class PatternAndPropertyUtils {
* The property bag to serialize.
* @return A pattern string approximately serializing the property bag.
*/
public static String propertiesToString(Properties properties) {
public static String propertiesToPatternString(DecimalFormatProperties properties) {
StringBuilder sb = new StringBuilder();
// Convenience references
@ -109,7 +57,7 @@ public class PatternAndPropertyUtils {
// Prefixes
if (ppp != null)
sb.append(ppp);
AffixPatternUtils.escape(pp, sb);
AffixUtils.escape(pp, sb);
int afterPrefixPos = sb.length();
// Figure out the grouping sizes.
@ -201,7 +149,7 @@ public class PatternAndPropertyUtils {
int beforeSuffixPos = sb.length();
if (psp != null)
sb.append(psp);
AffixPatternUtils.escape(ps, sb);
AffixUtils.escape(ps, sb);
// Resolve Padding
if (paddingWidth != -1) {
@ -212,24 +160,24 @@ public class PatternAndPropertyUtils {
int addedLength;
switch (paddingLocation) {
case BEFORE_PREFIX:
addedLength = escapePaddingString(paddingString, sb, 0);
addedLength = PatternStringUtils.escapePaddingString(paddingString, sb, 0);
sb.insert(0, '*');
afterPrefixPos += addedLength + 1;
beforeSuffixPos += addedLength + 1;
break;
case AFTER_PREFIX:
addedLength = escapePaddingString(paddingString, sb, afterPrefixPos);
addedLength = PatternStringUtils.escapePaddingString(paddingString, sb, afterPrefixPos);
sb.insert(afterPrefixPos, '*');
afterPrefixPos += addedLength + 1;
beforeSuffixPos += addedLength + 1;
break;
case BEFORE_SUFFIX:
escapePaddingString(paddingString, sb, beforeSuffixPos);
PatternStringUtils.escapePaddingString(paddingString, sb, beforeSuffixPos);
sb.insert(beforeSuffixPos, '*');
break;
case AFTER_SUFFIX:
sb.append('*');
escapePaddingString(paddingString, sb, sb.length());
PatternStringUtils.escapePaddingString(paddingString, sb, sb.length());
break;
}
}
@ -241,13 +189,13 @@ public class PatternAndPropertyUtils {
sb.append(';');
if (npp != null)
sb.append(npp);
AffixPatternUtils.escape(np, sb);
AffixUtils.escape(np, sb);
// Copy the positive digit format into the negative.
// This is optional; the pattern is the same as if '#' were appended here instead.
sb.append(sb, afterPrefixPos, beforeSuffixPos);
if (nsp != null)
sb.append(nsp);
AffixPatternUtils.escape(ns, sb);
AffixUtils.escape(ns, sb);
}
return sb.toString();
@ -296,6 +244,9 @@ public class PatternAndPropertyUtils {
* <p>
* Locale symbols are not allowed to contain the ASCII quote character.
*
* <p>
* This method is provided for backwards compatibility and should not be used in any new code.
*
* @param input
* The pattern to convert.
* @param symbols
@ -304,9 +255,7 @@ public class PatternAndPropertyUtils {
* true to convert from standard to localized notation; false to convert from localized to standard
* notation.
* @return The pattern expressed in the other notation.
* @deprecated ICU 59 This method is provided for backwards compatibility and should not be used in any new code.
*/
@Deprecated
public static String convertLocalized(String input, DecimalFormatSymbols symbols, boolean toLocalized) {
if (input == null)
return null;
@ -441,184 +390,4 @@ public class PatternAndPropertyUtils {
return result.toString();
}
public static final int IGNORE_ROUNDING_NEVER = 0;
public static final int IGNORE_ROUNDING_IF_CURRENCY = 1;
public static final int IGNORE_ROUNDING_ALWAYS = 2;
static void parse(String pattern, Properties properties, int ignoreRounding) {
if (pattern == null || pattern.length() == 0) {
// Backwards compatibility requires that we reset to the default values.
// TODO: Only overwrite the properties that "saveToProperties" normally touches?
properties.clear();
return;
}
// TODO: Use thread locals here?
ParsedPatternInfo patternInfo = PatternParser.parse(pattern);
saveToProperties(properties, patternInfo, ignoreRounding);
}
/** Finalizes the temporary data stored in the ParsedPatternInfo to the Properties. */
private static void saveToProperties(Properties properties, ParsedPatternInfo patternInfo, int _ignoreRounding) {
// Translate from PatternParseResult to Properties.
// Note that most data from "negative" is ignored per the specification of DecimalFormat.
ParsedSubpatternInfo positive = patternInfo.positive;
ParsedSubpatternInfo negative = patternInfo.negative;
boolean ignoreRounding;
if (_ignoreRounding == IGNORE_ROUNDING_NEVER) {
ignoreRounding = false;
} else if (_ignoreRounding == IGNORE_ROUNDING_IF_CURRENCY) {
ignoreRounding = positive.hasCurrencySign;
} else {
assert _ignoreRounding == IGNORE_ROUNDING_ALWAYS;
ignoreRounding = true;
}
// Grouping settings
short grouping1 = (short) (positive.groupingSizes & 0xffff);
short grouping2 = (short) ((positive.groupingSizes >>> 16) & 0xffff);
short grouping3 = (short) ((positive.groupingSizes >>> 32) & 0xffff);
if (grouping2 != -1) {
properties.setGroupingSize(grouping1);
} else {
properties.setGroupingSize(-1);
}
if (grouping3 != -1) {
properties.setSecondaryGroupingSize(grouping2);
} else {
properties.setSecondaryGroupingSize(-1);
}
// For backwards compatibility, require that the pattern emit at least one min digit.
int minInt, minFrac;
if (positive.integerTotal == 0 && positive.fractionTotal > 0) {
// patterns like ".##"
minInt = 0;
minFrac = Math.max(1, positive.fractionNumerals);
} else if (positive.integerNumerals == 0 && positive.fractionNumerals == 0) {
// patterns like "#.##"
minInt = 1;
minFrac = 0;
} else {
minInt = positive.integerNumerals;
minFrac = positive.fractionNumerals;
}
// Rounding settings
// Don't set basic rounding when there is a currency sign; defer to CurrencyUsage
if (positive.integerAtSigns > 0) {
properties.setMinimumFractionDigits(-1);
properties.setMaximumFractionDigits(-1);
properties.setRoundingIncrement(null);
properties.setMinimumSignificantDigits(positive.integerAtSigns);
properties.setMaximumSignificantDigits(positive.integerAtSigns + positive.integerTrailingHashSigns);
} else if (positive.rounding != null) {
if (!ignoreRounding) {
properties.setMinimumFractionDigits(minFrac);
properties.setMaximumFractionDigits(positive.fractionTotal);
properties.setRoundingIncrement(
positive.rounding.toBigDecimal().setScale(positive.fractionNumerals));
} else {
properties.setMinimumFractionDigits(-1);
properties.setMaximumFractionDigits(-1);
properties.setRoundingIncrement(null);
}
properties.setMinimumSignificantDigits(-1);
properties.setMaximumSignificantDigits(-1);
} else {
if (!ignoreRounding) {
properties.setMinimumFractionDigits(minFrac);
properties.setMaximumFractionDigits(positive.fractionTotal);
properties.setRoundingIncrement(null);
} else {
properties.setMinimumFractionDigits(-1);
properties.setMaximumFractionDigits(-1);
properties.setRoundingIncrement(null);
}
properties.setMinimumSignificantDigits(-1);
properties.setMaximumSignificantDigits(-1);
}
// If the pattern ends with a '.' then force the decimal point.
if (positive.hasDecimal && positive.fractionTotal == 0) {
properties.setDecimalSeparatorAlwaysShown(true);
} else {
properties.setDecimalSeparatorAlwaysShown(false);
}
// Scientific notation settings
if (positive.exponentZeros > 0) {
properties.setExponentSignAlwaysShown(positive.exponentHasPlusSign);
properties.setMinimumExponentDigits(positive.exponentZeros);
if (positive.integerAtSigns == 0) {
// patterns without '@' can define max integer digits, used for engineering notation
properties.setMinimumIntegerDigits(positive.integerNumerals);
properties.setMaximumIntegerDigits(positive.integerTotal);
} else {
// patterns with '@' cannot define max integer digits
properties.setMinimumIntegerDigits(1);
properties.setMaximumIntegerDigits(-1);
}
} else {
properties.setExponentSignAlwaysShown(false);
properties.setMinimumExponentDigits(-1);
properties.setMinimumIntegerDigits(minInt);
properties.setMaximumIntegerDigits(-1);
}
// Compute the affix patterns (required for both padding and affixes)
String posPrefix = patternInfo.getString(AffixPatternProvider.Flags.PREFIX);
String posSuffix = patternInfo.getString(0);
// Padding settings
if (positive.paddingEndpoints != 0) {
// The width of the positive prefix and suffix templates are included in the padding
int paddingWidth = positive.widthExceptAffixes + AffixPatternUtils.estimateLength(posPrefix)
+ AffixPatternUtils.estimateLength(posSuffix);
properties.setFormatWidth(paddingWidth);
String rawPaddingString = patternInfo.getString(AffixPatternProvider.Flags.PADDING);
if (rawPaddingString.length() == 1) {
properties.setPadString(rawPaddingString);
} else if (rawPaddingString.length() == 2) {
if (rawPaddingString.charAt(0) == '\'') {
properties.setPadString("'");
} else {
properties.setPadString(rawPaddingString);
}
} else {
properties.setPadString(rawPaddingString.substring(1, rawPaddingString.length() - 1));
}
assert positive.paddingLocation != null;
properties.setPadPosition(positive.paddingLocation);
} else {
properties.setFormatWidth(-1);
properties.setPadString(null);
properties.setPadPosition(null);
}
// Set the affixes
// Always call the setter, even if the prefixes are empty, especially in the case of the
// negative prefix pattern, to prevent default values from overriding the pattern.
properties.setPositivePrefixPattern(posPrefix);
properties.setPositiveSuffixPattern(posSuffix);
if (negative != null) {
properties.setNegativePrefixPattern(patternInfo
.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN | AffixPatternProvider.Flags.PREFIX));
properties.setNegativeSuffixPattern(patternInfo.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN));
} else {
properties.setNegativePrefixPattern(null);
properties.setNegativeSuffixPattern(null);
}
// Set the magnitude multiplier
if (positive.hasPercentSign) {
properties.setMagnitudeMultiplier(2);
} else if (positive.hasPerMilleSign) {
properties.setMagnitudeMultiplier(3);
} else {
properties.setMagnitudeMultiplier(0);
}
}
}

View file

@ -133,7 +133,7 @@ public class RoundingUtils {
* @param properties The property bag.
* @return A {@link MathContext}. Never null.
*/
public static MathContext getMathContextOrUnlimited(Properties properties) {
public static MathContext getMathContextOrUnlimited(DecimalFormatProperties properties) {
MathContext mathContext = properties.getMathContext();
if (mathContext == null) {
RoundingMode roundingMode = properties.getRoundingMode();
@ -151,7 +151,7 @@ public class RoundingUtils {
* @param properties The property bag.
* @return A {@link MathContext}. Never null.
*/
public static MathContext getMathContextOr34Digits(Properties properties) {
public static MathContext getMathContextOr34Digits(DecimalFormatProperties properties) {
MathContext mathContext = properties.getMathContext();
if (mathContext == null) {
RoundingMode roundingMode = properties.getRoundingMode();

View file

@ -12,7 +12,7 @@ package com.ibm.icu.text;
import java.text.ParsePosition;
import java.util.Locale;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.ULocale;
@ -122,11 +122,11 @@ public class CompactDecimalFormat extends DecimalFormat {
CompactDecimalFormat(ULocale locale, CompactStyle style) {
// Minimal properties: let the non-shim code path do most of the logic for us.
symbols = DecimalFormatSymbols.getInstance(locale);
properties = new Properties();
properties = new DecimalFormatProperties();
properties.setCompactStyle(style);
properties.setGroupingSize(-2); // do not forward grouping information
properties.setMinimumGroupingDigits(2);
exportedProperties = new Properties();
exportedProperties = new DecimalFormatProperties();
refreshFormatter();
}

View file

@ -13,10 +13,11 @@ import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition;
import com.ibm.icu.impl.number.AffixPatternUtils;
import com.ibm.icu.impl.number.AffixUtils;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.Parse;
import com.ibm.icu.impl.number.PatternAndPropertyUtils;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringUtils;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.math.MathContext;
@ -30,8 +31,6 @@ import com.ibm.icu.util.ULocale.Category;
import newapi.FormattedNumber;
import newapi.LocalizedNumberFormatter;
import newapi.NumberFormatter;
import newapi.NumberPropertyMapper;
import newapi.impl.MacroProps;
import newapi.impl.Padder.PadPosition;
/**
@ -252,7 +251,7 @@ public class DecimalFormat extends NumberFormat {
* In principle this should be final, but serialize and clone won't work if it is final. Does not
* need to be volatile because the reference never changes.
*/
/* final */ transient Properties properties;
/* final */ transient DecimalFormatProperties properties;
/**
* The symbols for the current locale. Volatile because threads may read and write at the same
@ -271,7 +270,7 @@ public class DecimalFormat extends NumberFormat {
* The effective properties as exported from the formatter object. Volatile because threads may
* read and write at the same time.
*/
transient volatile Properties exportedProperties;
transient volatile DecimalFormatProperties exportedProperties;
//=====================================================================================//
// CONSTRUCTORS //
@ -298,10 +297,10 @@ public class DecimalFormat extends NumberFormat {
ULocale def = ULocale.getDefault(ULocale.Category.FORMAT);
String pattern = getPattern(def, NumberFormat.NUMBERSTYLE);
symbols = getDefaultSymbols();
properties = new Properties();
exportedProperties = new Properties();
properties = new DecimalFormatProperties();
exportedProperties = new DecimalFormatProperties();
// Regression: ignore pattern rounding information if the pattern has currency symbols.
setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY);
setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
refreshFormatter();
}
@ -327,10 +326,10 @@ public class DecimalFormat extends NumberFormat {
*/
public DecimalFormat(String pattern) {
symbols = getDefaultSymbols();
properties = new Properties();
exportedProperties = new Properties();
properties = new DecimalFormatProperties();
exportedProperties = new DecimalFormatProperties();
// Regression: ignore pattern rounding information if the pattern has currency symbols.
setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY);
setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
refreshFormatter();
}
@ -356,10 +355,10 @@ public class DecimalFormat extends NumberFormat {
*/
public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
this.symbols = (DecimalFormatSymbols) symbols.clone();
properties = new Properties();
exportedProperties = new Properties();
properties = new DecimalFormatProperties();
exportedProperties = new DecimalFormatProperties();
// Regression: ignore pattern rounding information if the pattern has currency symbols.
setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY);
setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
refreshFormatter();
}
@ -393,8 +392,8 @@ public class DecimalFormat extends NumberFormat {
/** Package-private constructor used by NumberFormat. */
DecimalFormat(String pattern, DecimalFormatSymbols symbols, int choice) {
this.symbols = (DecimalFormatSymbols) symbols.clone();
properties = new Properties();
exportedProperties = new Properties();
properties = new DecimalFormatProperties();
exportedProperties = new DecimalFormatProperties();
// If choice is a currency type, ignore the rounding information.
if (choice == CURRENCYSTYLE
|| choice == ISOCURRENCYSTYLE
@ -402,9 +401,9 @@ public class DecimalFormat extends NumberFormat {
|| choice == CASHCURRENCYSTYLE
|| choice == STANDARDCURRENCYSTYLE
|| choice == PLURALCURRENCYSTYLE) {
setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_ALWAYS);
setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_ALWAYS);
} else {
setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY);
setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
}
refreshFormatter();
}
@ -445,7 +444,7 @@ public class DecimalFormat extends NumberFormat {
* @stable ICU 2.0
*/
public synchronized void applyPattern(String pattern) {
setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER);
setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_NEVER);
// Backwards compatibility: clear out user-specified prefix and suffix,
// as well as CurrencyPluralInfo.
properties.setPositivePrefix(null);
@ -469,7 +468,7 @@ public class DecimalFormat extends NumberFormat {
* @stable ICU 2.0
*/
public synchronized void applyLocalizedPattern(String localizedPattern) {
String pattern = PatternAndPropertyUtils.convertLocalized(localizedPattern, symbols, false);
String pattern = PatternStringUtils.convertLocalized(localizedPattern, symbols, false);
applyPattern(pattern);
}
@ -483,7 +482,7 @@ public class DecimalFormat extends NumberFormat {
DecimalFormat other = (DecimalFormat) super.clone();
other.symbols = (DecimalFormatSymbols) symbols.clone();
other.properties = properties.clone();
other.exportedProperties = new Properties();
other.exportedProperties = new DecimalFormatProperties();
other.refreshFormatter();
return other;
}
@ -525,15 +524,15 @@ public class DecimalFormat extends NumberFormat {
// Extra int for possible future use:
ois.readInt();
// 1) Property Bag
properties = (Properties) ois.readObject();
properties = (DecimalFormatProperties) ois.readObject();
// 2) DecimalFormatSymbols
symbols = (DecimalFormatSymbols) ois.readObject();
// Re-build transient fields
exportedProperties = new Properties();
exportedProperties = new DecimalFormatProperties();
refreshFormatter();
} else {
///// LEGACY SERIALIZATION FORMAT /////
properties = new Properties();
properties = new DecimalFormatProperties();
// Loop through the fields. Not all fields necessarily exist in the serialization.
String pp = null, ppp = null, ps = null, psp = null;
String np = null, npp = null, ns = null, nsp = null;
@ -667,7 +666,7 @@ public class DecimalFormat extends NumberFormat {
if (symbols == null) {
symbols = getDefaultSymbols();
}
exportedProperties = new Properties();
exportedProperties = new DecimalFormatProperties();
refreshFormatter();
}
}
@ -775,7 +774,7 @@ public class DecimalFormat extends NumberFormat {
*/
@Override
public Number parse(String text, ParsePosition parsePosition) {
Properties pprops = threadLocalProperties.get();
DecimalFormatProperties pprops = threadLocalProperties.get();
synchronized (this) {
pprops.copyFrom(properties);
}
@ -796,7 +795,7 @@ public class DecimalFormat extends NumberFormat {
@Override
public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosition) {
try {
Properties pprops = threadLocalProperties.get();
DecimalFormatProperties pprops = threadLocalProperties.get();
synchronized (this) {
pprops.copyFrom(properties);
}
@ -2377,13 +2376,13 @@ public class DecimalFormat extends NumberFormat {
// to keep affix patterns intact. In particular, pull rounding properties
// so that CurrencyUsage is reflected properly.
// TODO: Consider putting this logic in PatternString.java instead.
Properties tprops = threadLocalProperties.get().copyFrom(properties);
DecimalFormatProperties tprops = threadLocalProperties.get().copyFrom(properties);
if (useCurrency(properties)) {
tprops.setMinimumFractionDigits(exportedProperties.getMinimumFractionDigits());
tprops.setMaximumFractionDigits(exportedProperties.getMaximumFractionDigits());
tprops.setRoundingIncrement(exportedProperties.getRoundingIncrement());
}
return PatternAndPropertyUtils.propertiesToString(tprops);
return PatternStringUtils.propertiesToPatternString(tprops);
}
/**
@ -2396,7 +2395,7 @@ public class DecimalFormat extends NumberFormat {
*/
public synchronized String toLocalizedPattern() {
String pattern = toPattern();
return PatternAndPropertyUtils.convertLocalized(pattern, symbols, true);
return PatternStringUtils.convertLocalized(pattern, symbols, true);
}
/**
@ -2422,11 +2421,11 @@ public class DecimalFormat extends NumberFormat {
return formatter.format(number).getFixedDecimal();
}
private static final ThreadLocal<Properties> threadLocalProperties =
new ThreadLocal<Properties>() {
private static final ThreadLocal<DecimalFormatProperties> threadLocalProperties =
new ThreadLocal<DecimalFormatProperties>() {
@Override
protected Properties initialValue() {
return new Properties();
protected DecimalFormatProperties initialValue() {
return new DecimalFormatProperties();
}
};
@ -2437,7 +2436,6 @@ public class DecimalFormat extends NumberFormat {
// The only time when this happens is during legacy deserialization.
return;
}
MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, exportedProperties);
ULocale locale = this.getLocale(ULocale.ACTUAL_LOCALE);
if (locale == null) {
// Constructor
@ -2448,7 +2446,7 @@ public class DecimalFormat extends NumberFormat {
locale = symbols.getULocale();
}
assert locale != null;
formatter = NumberFormatter.with().macros(macros).locale(locale);
formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedProperties).locale(locale);
}
/**
@ -2478,14 +2476,14 @@ public class DecimalFormat extends NumberFormat {
* Returns true if the currency is set in The property bag or if currency symbols are present in
* the prefix/suffix pattern.
*/
private static boolean useCurrency(Properties properties) {
private static boolean useCurrency(DecimalFormatProperties properties) {
return ((properties.getCurrency() != null)
|| properties.getCurrencyPluralInfo() != null
|| properties.getCurrencyUsage() != null
|| AffixPatternUtils.hasCurrencySymbols(properties.getPositivePrefixPattern())
|| AffixPatternUtils.hasCurrencySymbols(properties.getPositiveSuffixPattern())
|| AffixPatternUtils.hasCurrencySymbols(properties.getNegativePrefixPattern())
|| AffixPatternUtils.hasCurrencySymbols(properties.getNegativeSuffixPattern()));
|| AffixUtils.hasCurrencySymbols(properties.getPositivePrefixPattern())
|| AffixUtils.hasCurrencySymbols(properties.getPositiveSuffixPattern())
|| AffixUtils.hasCurrencySymbols(properties.getNegativePrefixPattern())
|| AffixUtils.hasCurrencySymbols(properties.getNegativeSuffixPattern()));
}
/**
@ -2495,15 +2493,15 @@ public class DecimalFormat extends NumberFormat {
* @param ignoreRounding Whether to leave out rounding information (minFrac, maxFrac, and rounding
* increment) when parsing the pattern. This may be desirable if a custom rounding mode, such
* as CurrencyUsage, is to be used instead. One of {@link
* PatternAndPropertyUtils#IGNORE_ROUNDING_ALWAYS}, {@link PatternAndPropertyUtils#IGNORE_ROUNDING_IF_CURRENCY},
* or {@link PatternAndPropertyUtils#IGNORE_ROUNDING_NEVER}.
* PatternStringParser#IGNORE_ROUNDING_ALWAYS}, {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY},
* or {@link PatternStringParser#IGNORE_ROUNDING_NEVER}.
* @see PatternAndPropertyUtils#parseToExistingProperties
*/
void setPropertiesFromPattern(String pattern, int ignoreRounding) {
if (pattern == null) {
throw new NullPointerException();
}
PatternAndPropertyUtils.parseToExistingProperties(pattern, properties, ignoreRounding);
PatternStringParser.parseToExistingProperties(pattern, properties, ignoreRounding);
}
/**
@ -2527,7 +2525,7 @@ public class DecimalFormat extends NumberFormat {
* @deprecated This API is ICU internal only.
*/
@Deprecated
public void set(Properties props);
public void set(DecimalFormatProperties props);
}
/**

View file

@ -10,7 +10,7 @@ package com.ibm.icu.text;
import java.text.ParsePosition;
import com.ibm.icu.impl.number.FormatQuantity4;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
//===================================================================
// NFSubstitution (abstract base class)
@ -1241,7 +1241,7 @@ class FractionalPartSubstitution extends NFSubstitution {
// (this is slower, but more accurate, than doing it from the
// other end)
FormatQuantity4 fq = new FormatQuantity4(number);
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(number);
fq.roundToInfinity(); // ensure doubles are resolved using slow path
boolean pad = false;
@ -1316,7 +1316,7 @@ class FractionalPartSubstitution extends NFSubstitution {
double result;
int digit;
FormatQuantity4 fq = new FormatQuantity4();
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
int leadingZeros = 0;
while (workText.length() > 0 && workPos.getIndex() != 0) {
workPos.setIndex(0);

View file

@ -7,18 +7,19 @@ import java.util.Map;
import java.util.Set;
import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.PatternParser;
import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.CompactDecimalFormat.CompactType;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.util.ULocale;
import newapi.MutablePatternModifier.ImmutableMurkyModifier;
import newapi.impl.CompactData;
import newapi.impl.MicroProps;
import newapi.impl.MicroPropsGenerator;
import newapi.impl.MutablePatternModifier;
import newapi.impl.MutablePatternModifier.ImmutableMurkyModifier;
public class CompactNotation extends Notation {
@ -78,7 +79,7 @@ public class CompactNotation extends Notation {
Set<String> allPatterns = data.getAllPatterns();
for (String patternString : allPatterns) {
CompactModInfo info = new CompactModInfo();
ParsedPatternInfo patternInfo = PatternParser.parse(patternString);
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
buildReference.setPatternInfo(patternInfo);
info.mod = buildReference.createImmutable();
info.numDigits = patternInfo.positive.integerTotal;
@ -88,7 +89,7 @@ public class CompactNotation extends Notation {
}
@Override
public MicroProps processQuantity(FormatQuantity input) {
public MicroProps processQuantity(DecimalQuantity input) {
MicroProps micros = parent.processQuantity(input);
assert micros.rounding != null;
@ -119,7 +120,7 @@ public class CompactNotation extends Notation {
// Unsafe code path.
// Overwrite the PatternInfo in the existing modMiddle
assert micros.modMiddle instanceof MutablePatternModifier;
ParsedPatternInfo patternInfo = PatternParser.parse(patternString);
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
((MutablePatternModifier) micros.modMiddle).setPatternInfo(patternInfo);
numDigits = patternInfo.positive.integerTotal;
}

View file

@ -20,7 +20,7 @@ public abstract class CurrencyRounder extends Rounder {
*
* <p>
* <strong>Calling this method is <em>not required</em></strong>, because the currency specified in
* {@link NumberFormatter#unit(MeasureUnit)} or via a {@link CurrencyAmount} passed into
* {@link NumberFormatterSettings#unit(MeasureUnit)} or via a {@link CurrencyAmount} passed into
* {@link LocalizedNumberFormatter#format(Measure)} is automatically applied to currency rounding strategies.
* However, this method enables you to override that automatic association.
*

View file

@ -8,7 +8,7 @@ import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.util.Arrays;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.text.PluralRules.IFixedDecimal;
import com.ibm.icu.util.ICUUncheckedIOException;
@ -17,10 +17,10 @@ import newapi.impl.MicroProps;
public class FormattedNumber {
NumberStringBuilder nsb;
FormatQuantity fq;
DecimalQuantity fq;
MicroProps micros;
FormattedNumber(NumberStringBuilder nsb, FormatQuantity fq, MicroProps micros) {
FormattedNumber(NumberStringBuilder nsb, DecimalQuantity fq, MicroProps micros) {
this.nsb = nsb;
this.fq = fq;
this.micros = micros;

View file

@ -2,8 +2,8 @@
// License & terms of use: http://www.unicode.org/copyright.html#License
package newapi;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
public class Grouper {
@ -85,7 +85,7 @@ public class Grouper {
return getInstance(grouping1, grouping2, min2);
}
boolean groupAtPosition(int position, FormatQuantity value) {
boolean groupAtPosition(int position, DecimalQuantity value) {
assert grouping1 != -2;
if (grouping1 == -1 || grouping1 == 0) {
// Either -1 or 0 means "no grouping"

View file

@ -5,8 +5,8 @@ package newapi;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.FormatQuantity4;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.util.Measure;
import com.ibm.icu.util.MeasureUnit;
@ -21,22 +21,22 @@ public class LocalizedNumberFormatter extends NumberFormatterSettings<LocalizedN
volatile long callCountInternal; // do not access directly; use callCount instead
volatile LocalizedNumberFormatter savedWithUnit;
volatile Worker1 compiled;
volatile NumberFormatterImpl compiled;
LocalizedNumberFormatter(NumberFormatterSettings<?> parent, int key, Object value) {
super(parent, key, value);
}
public FormattedNumber format(long input) {
return format(new FormatQuantity4(input));
return format(new DecimalQuantity_DualStorageBCD(input));
}
public FormattedNumber format(double input) {
return format(new FormatQuantity4(input));
return format(new DecimalQuantity_DualStorageBCD(input));
}
public FormattedNumber format(Number input) {
return format(new FormatQuantity4(input));
return format(new DecimalQuantity_DualStorageBCD(input));
}
public FormattedNumber format(Measure input) {
@ -68,18 +68,18 @@ public class LocalizedNumberFormatter extends NumberFormatterSettings<LocalizedN
* @deprecated ICU 60 This API is ICU internal only.
*/
@Deprecated
public FormattedNumber format(FormatQuantity fq) {
public FormattedNumber format(DecimalQuantity fq) {
MacroProps macros = resolve();
NumberStringBuilder string = new NumberStringBuilder();
long currentCount = callCount.incrementAndGet(this);
MicroProps micros;
if (currentCount == macros.threshold.longValue()) {
compiled = Worker1.fromMacros(macros);
compiled = NumberFormatterImpl.fromMacros(macros);
micros = compiled.apply(fq, string);
} else if (compiled != null) {
micros = compiled.apply(fq, string);
} else {
micros = Worker1.applyStatic(macros, fq, string);
micros = NumberFormatterImpl.applyStatic(macros, fq, string);
}
return new FormattedNumber(string, fq, micros);
}

View file

@ -4,8 +4,12 @@ package newapi;
import java.util.Locale;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.util.ULocale;
import newapi.impl.MacroProps;
public final class NumberFormatter {
private static final UnlocalizedNumberFormatter BASE = new UnlocalizedNumberFormatter();
@ -43,4 +47,15 @@ public final class NumberFormatter {
public static LocalizedNumberFormatter withLocale(ULocale locale) {
return BASE.locale(locale);
}
/**
* @internal
* @deprecated ICU 60 This API is ICU internal only.
*/
@Deprecated
public static UnlocalizedNumberFormatter fromDecimalFormat(DecimalFormatProperties properties,
DecimalFormatSymbols symbols, DecimalFormatProperties exportedProperties) {
MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, exportedProperties);
return NumberFormatter.with().macros(macros);
}
}

View file

@ -2,10 +2,10 @@
// License & terms of use: http://www.unicode.org/copyright.html#License
package newapi;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.PatternParser;
import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.modifiers.ConstantAffixModifier;
import com.ibm.icu.text.CompactDecimalFormat.CompactType;
import com.ibm.icu.text.DecimalFormatSymbols;
@ -20,20 +20,30 @@ import com.ibm.icu.util.ULocale;
import newapi.NumberFormatter.DecimalMarkDisplay;
import newapi.NumberFormatter.SignDisplay;
import newapi.NumberFormatter.UnitWidth;
import newapi.impl.LongNameHandler;
import newapi.impl.MacroProps;
import newapi.impl.MicroProps;
import newapi.impl.MicroPropsGenerator;
import newapi.impl.MutablePatternModifier;
import newapi.impl.Padder;
public class Worker1 {
/**
* This is the "brain" of the number formatting pipeline. It ties all the pieces together, taking in a MacroProps and a
* DecimalQuantity and outputting a properly formatted number string.
*
* <p>
* This class, as well as NumberPropertyMapper, could go into the impl package, but they depend on too many
* package-private members of the public APIs.
*/
class NumberFormatterImpl {
public static Worker1 fromMacros(MacroProps macros) {
public static NumberFormatterImpl fromMacros(MacroProps macros) {
// Build a "safe" MicroPropsGenerator, which is thread-safe and can be used repeatedly.
MicroPropsGenerator microPropsGenerator = macrosToMicroGenerator(macros, true);
return new Worker1(microPropsGenerator);
return new NumberFormatterImpl(microPropsGenerator);
}
public static MicroProps applyStatic(MacroProps macros, FormatQuantity inValue, NumberStringBuilder outString) {
public static MicroProps applyStatic(MacroProps macros, DecimalQuantity inValue, NumberStringBuilder outString) {
// Build an "unsafe" MicroPropsGenerator, which is cheaper but can be used only once.
MicroPropsGenerator microPropsGenerator = macrosToMicroGenerator(macros, false);
MicroProps micros = microPropsGenerator.processQuantity(inValue);
@ -45,11 +55,11 @@ public class Worker1 {
final MicroPropsGenerator microPropsGenerator;
private Worker1(MicroPropsGenerator microsGenerator) {
private NumberFormatterImpl(MicroPropsGenerator microsGenerator) {
this.microPropsGenerator = microsGenerator;
}
public MicroProps apply(FormatQuantity inValue, NumberStringBuilder outString) {
public MicroProps apply(DecimalQuantity inValue, NumberStringBuilder outString) {
MicroProps micros = microPropsGenerator.processQuantity(inValue);
microsToString(micros, inValue, outString);
return micros;
@ -75,7 +85,7 @@ public class Worker1 {
String innerPattern = null;
LongNameHandler longNames = null;
Rounder defaultRounding = Rounder.none();
Rounder defaultRounding = Rounder.unlimited();
Currency currency = DEFAULT_CURRENCY;
UnitWidth unitWidth = null;
boolean perMille = false;
@ -131,7 +141,7 @@ public class Worker1 {
}
// Parse the pattern, which is used for grouping and affixes only.
ParsedPatternInfo patternInfo = PatternParser.parse(innerPattern);
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(innerPattern);
// Symbols
if (macros.symbols == null) {
@ -242,16 +252,16 @@ public class Worker1 {
//////////
/**
* Synthesizes the output string from a MicroProps and FormatQuantity.
* Synthesizes the output string from a MicroProps and DecimalQuantity.
*
* @param micros
* The MicroProps after the quantity has been consumed. Will not be mutated.
* @param quantity
* The FormatQuantity to be rendered. May be mutated.
* The DecimalQuantity to be rendered. May be mutated.
* @param string
* The output string. Will be mutated.
*/
private static void microsToString(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) {
private static void microsToString(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) {
quantity.adjustMagnitude(micros.multiplier);
micros.rounding.apply(quantity);
if (micros.integerWidth.maxInt == -1) {
@ -265,7 +275,7 @@ public class Worker1 {
length += micros.padding.applyModsAndMaybePad(micros, string, 0, length);
}
private static int writeNumber(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) {
private static int writeNumber(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) {
int length = 0;
if (quantity.isInfinite()) {
length += string.insert(length, micros.symbols.getInfinity(), NumberFormat.Field.INTEGER);
@ -290,7 +300,7 @@ public class Worker1 {
return length;
}
private static int writeIntegerDigits(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) {
private static int writeIntegerDigits(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) {
int length = 0;
int integerCount = quantity.getUpperDisplayMagnitude() + 1;
for (int i = 0; i < integerCount; i++) {
@ -313,7 +323,7 @@ public class Worker1 {
return length;
}
private static int writeFractionDigits(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) {
private static int writeFractionDigits(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) {
int length = 0;
int fractionCount = -quantity.getLowerDisplayMagnitude();
for (int i = 0; i < fractionCount; i++) {

View file

@ -377,6 +377,7 @@ public abstract class NumberFormatterSettings<T extends NumberFormatterSettings<
// Although the linked-list fluent storage approach requires this method,
// my benchmarks show that linked-list is still faster than a full clone
// of a MacroProps object at each step.
// TODO: Remove the reference to the parent after the macros are resolved?
MacroProps macros = new MacroProps();
NumberFormatterSettings<?> current = this;
while (current != null) {

View file

@ -6,11 +6,10 @@ import java.math.BigDecimal;
import java.math.MathContext;
import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.impl.number.AffixPatternUtils;
import com.ibm.icu.impl.number.PatternAndPropertyUtils;
import com.ibm.icu.impl.number.PatternParser;
import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.AffixUtils;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.RoundingUtils;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.CurrencyPluralInfo;
@ -30,11 +29,15 @@ import newapi.impl.MacroProps;
import newapi.impl.MultiplierImpl;
import newapi.impl.Padder;
/** @author sffc */
public final class NumberPropertyMapper {
/**
* <p>
* This class, as well as NumberFormatterImpl, could go into the impl package, but they depend on too many
* package-private members of the public APIs.
*/
final class NumberPropertyMapper {
/** Convenience method to create a NumberFormatter directly from Properties. */
public static UnlocalizedNumberFormatter create(Properties properties, DecimalFormatSymbols symbols) {
public static UnlocalizedNumberFormatter create(DecimalFormatProperties properties, DecimalFormatSymbols symbols) {
MacroProps macros = oldToNew(properties, symbols, null);
return NumberFormatter.with().macros(macros);
}
@ -44,14 +47,14 @@ public final class NumberPropertyMapper {
* public API if there is demand.
*/
public static UnlocalizedNumberFormatter create(String pattern, DecimalFormatSymbols symbols) {
Properties properties = PatternAndPropertyUtils.parseToProperties(pattern);
DecimalFormatProperties properties = PatternStringParser.parseToProperties(pattern);
return create(properties, symbols);
}
/**
* Creates a new {@link MacroProps} object based on the content of a {@link Properties} object. In other words, maps
* Properties to MacroProps. This function is used by the JDK-compatibility API to call into the ICU 60 fluent
* number formatting pipeline.
* Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties} object. In
* other words, maps Properties to MacroProps. This function is used by the JDK-compatibility API to call into the
* ICU 60 fluent number formatting pipeline.
*
* @param properties
* The property bag to be mapped.
@ -61,8 +64,8 @@ public final class NumberPropertyMapper {
* A property bag in which to store validated properties.
* @return A new MacroProps containing all of the information in the Properties.
*/
public static MacroProps oldToNew(Properties properties, DecimalFormatSymbols symbols,
Properties exportedProperties) {
public static MacroProps oldToNew(DecimalFormatProperties properties, DecimalFormatSymbols symbols,
DecimalFormatProperties exportedProperties) {
MacroProps macros = new MacroProps();
ULocale locale = symbols.getULocale();
@ -85,13 +88,13 @@ public final class NumberPropertyMapper {
AffixPatternProvider affixProvider;
if (properties.getCurrencyPluralInfo() == null) {
affixProvider = new PropertiesAffixPatternProvider(
properties.getPositivePrefix() != null ? AffixPatternUtils.escape(properties.getPositivePrefix())
properties.getPositivePrefix() != null ? AffixUtils.escape(properties.getPositivePrefix())
: properties.getPositivePrefixPattern(),
properties.getPositiveSuffix() != null ? AffixPatternUtils.escape(properties.getPositiveSuffix())
properties.getPositiveSuffix() != null ? AffixUtils.escape(properties.getPositiveSuffix())
: properties.getPositiveSuffixPattern(),
properties.getNegativePrefix() != null ? AffixPatternUtils.escape(properties.getNegativePrefix())
properties.getNegativePrefix() != null ? AffixUtils.escape(properties.getNegativePrefix())
: properties.getNegativePrefixPattern(),
properties.getNegativeSuffix() != null ? AffixPatternUtils.escape(properties.getNegativeSuffix())
properties.getNegativeSuffix() != null ? AffixUtils.escape(properties.getNegativeSuffix())
: properties.getNegativeSuffixPattern());
} else {
affixProvider = new CurrencyPluralInfoAffixProvider(properties.getCurrencyPluralInfo());
@ -371,8 +374,8 @@ public final class NumberPropertyMapper {
@Override
public boolean positiveHasPlusSign() {
return AffixPatternUtils.containsType(posPrefixPattern, AffixPatternUtils.TYPE_PLUS_SIGN)
|| AffixPatternUtils.containsType(posSuffixPattern, AffixPatternUtils.TYPE_PLUS_SIGN);
return AffixUtils.containsType(posPrefixPattern, AffixUtils.TYPE_PLUS_SIGN)
|| AffixUtils.containsType(posSuffixPattern, AffixUtils.TYPE_PLUS_SIGN);
}
@Override
@ -382,24 +385,22 @@ public final class NumberPropertyMapper {
@Override
public boolean negativeHasMinusSign() {
return AffixPatternUtils.containsType(negPrefixPattern, AffixPatternUtils.TYPE_MINUS_SIGN)
|| AffixPatternUtils.containsType(negSuffixPattern, AffixPatternUtils.TYPE_MINUS_SIGN);
return AffixUtils.containsType(negPrefixPattern, AffixUtils.TYPE_MINUS_SIGN)
|| AffixUtils.containsType(negSuffixPattern, AffixUtils.TYPE_MINUS_SIGN);
}
@Override
public boolean hasCurrencySign() {
return AffixPatternUtils.hasCurrencySymbols(posPrefixPattern)
|| AffixPatternUtils.hasCurrencySymbols(posSuffixPattern)
|| AffixPatternUtils.hasCurrencySymbols(negPrefixPattern)
|| AffixPatternUtils.hasCurrencySymbols(negSuffixPattern);
return AffixUtils.hasCurrencySymbols(posPrefixPattern) || AffixUtils.hasCurrencySymbols(posSuffixPattern)
|| AffixUtils.hasCurrencySymbols(negPrefixPattern)
|| AffixUtils.hasCurrencySymbols(negSuffixPattern);
}
@Override
public boolean containsSymbolType(int type) {
return AffixPatternUtils.containsType(posPrefixPattern, type)
|| AffixPatternUtils.containsType(posSuffixPattern, type)
|| AffixPatternUtils.containsType(negPrefixPattern, type)
|| AffixPatternUtils.containsType(negSuffixPattern, type);
return AffixUtils.containsType(posPrefixPattern, type) || AffixUtils.containsType(posSuffixPattern, type)
|| AffixUtils.containsType(negPrefixPattern, type)
|| AffixUtils.containsType(negSuffixPattern, type);
}
}
@ -409,8 +410,8 @@ public final class NumberPropertyMapper {
public CurrencyPluralInfoAffixProvider(CurrencyPluralInfo cpi) {
affixesByPlural = new ParsedPatternInfo[StandardPlural.COUNT];
for (StandardPlural plural : StandardPlural.VALUES) {
affixesByPlural[plural.ordinal()] = PatternParser
.parse(cpi.getCurrencyPluralPattern(plural.getKeyword()));
affixesByPlural[plural.ordinal()] = PatternStringParser
.parseToPatternInfo(cpi.getCurrencyPluralPattern(plural.getKeyword()));
}
}

View file

@ -6,7 +6,7 @@ import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.RoundingUtils;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.Currency.CurrencyUsage;
@ -25,14 +25,55 @@ public abstract class Rounder implements Cloneable {
mathContext = RoundingUtils.mathContextUnlimited(RoundingMode.HALF_EVEN);
}
public static Rounder none() {
/**
* Show all available digits to full precision.
*
* <p>
* <strong>NOTE:</strong> If you are formatting <em>doubles</em> and you know that the number of fraction places or
* significant digits is bounded, consider using {@link #maxFraction} or {@link #maxDigits} instead to maximize
* performance.
*
* @return A rounding strategy for {@link NumberFormatterSettings#rounding}.
*/
public static Rounder unlimited() {
return constructInfinite();
}
/**
* Show numbers rounded if necessary to the nearest integer.
*
* @return A rounding strategy for {@link NumberFormatterSettings#rounding}.
*/
public static FractionRounder integer() {
return constructFraction(0, 0);
}
/**
* Show numbers rounded if necessary to a certain number of fraction places (digits after the decimal mark).
* Additionally, pad with zeros to ensure that this number digits are always shown.
*
* <p>
* Example output with minMaxFractionDigits = 3:
*
* <p>
* 87,650.000<br>
* 8,765.000<br>
* 876.500<br>
* 87.650<br>
* 8.765<br>
* 0.876<br>
* 0.088<br>
* 0.009<br>
* 0.000 (zero)
*
* <p>
* This method is equivalent to {@link #minMaxFraction} with both arguments equal.
*
* @param minMaxFractionDigits
* The minimum and maximum number of digits to display after the decimal mark (rounding if too long or
* padding with zeros if too short).
* @return A rounding strategy for {@link NumberFormatterSettings#rounding}.
*/
public static FractionRounder fixedFraction(int minMaxFractionDigits) {
if (minMaxFractionDigits >= 0 && minMaxFractionDigits <= MAX_VALUE) {
return constructFraction(minMaxFractionDigits, minMaxFractionDigits);
@ -41,6 +82,18 @@ public abstract class Rounder implements Cloneable {
}
}
/**
* Always show a certain number of digits after the decimal mark, padding with zeros if necessary. Do not perform
* rounding (display numbers to their full precision).
*
* <p>
* <strong>NOTE:</strong> If you are formatting <em>doubles</em> and you know that the number of fraction places is
* bounded, consider using {@link #fixedFraction} or {@link #minMaxFraction} instead to maximize performance.
*
* @param minFractionDigits
* The minimum number of digits to display after the decimal mark (padding with zeros if necessary).
* @return A rounding strategy for {@link NumberFormatterSettings#rounding}.
*/
public static FractionRounder minFraction(int minFractionDigits) {
if (minFractionDigits >= 0 && minFractionDigits < MAX_VALUE) {
return constructFraction(minFractionDigits, -1);
@ -49,6 +102,14 @@ public abstract class Rounder implements Cloneable {
}
}
/**
* Show numbers rounded if necessary to a certain number of fraction places (digits after the decimal mark). Unlike
* the other fraction rounding strategies, this strategy does <em>not</em> pad zeros to the end of the number.
*
* @param maxFractionDigits
* The maximum number of digits to display after the decimal mark (rounding if necessary).
* @return A rounding strategy for {@link NumberFormatterSettings#rounding}.
*/
public static FractionRounder maxFraction(int maxFractionDigits) {
if (maxFractionDigits >= 0 && maxFractionDigits < MAX_VALUE) {
return constructFraction(0, maxFractionDigits);
@ -57,6 +118,16 @@ public abstract class Rounder implements Cloneable {
}
}
/**
* Show numbers rounded if necessary to a certain number of fraction places (digits after the decimal mark); in
* addition, always show a certain number of digits after the decimal mark, padding with zeros if necessary.
*
* @param minFractionDigits
* The minimum number of digits to display after the decimal mark (padding with zeros if necessary).
* @param maxFractionDigits
* The maximum number of digits to display after the decimal mark (rounding if necessary).
* @return A rounding strategy for {@link NumberFormatterSettings#rounding}.
*/
public static FractionRounder minMaxFraction(int minFractionDigits, int maxFractionDigits) {
if (minFractionDigits >= 0 && maxFractionDigits <= MAX_VALUE && minFractionDigits <= maxFractionDigits) {
return constructFraction(minFractionDigits, maxFractionDigits);
@ -90,7 +161,8 @@ public abstract class Rounder implements Cloneable {
}
public static Rounder minMaxDigits(int minSignificantDigits, int maxSignificantDigits) {
if (minSignificantDigits > 0 && maxSignificantDigits <= MAX_VALUE && minSignificantDigits <= maxSignificantDigits) {
if (minSignificantDigits > 0 && maxSignificantDigits <= MAX_VALUE
&& minSignificantDigits <= maxSignificantDigits) {
return constructSignificant(minSignificantDigits, maxSignificantDigits);
} else {
throw new IllegalArgumentException("Significant digits must be between 0 and " + MAX_VALUE);
@ -154,6 +226,13 @@ public abstract class Rounder implements Cloneable {
}
}
/**
* @internal
* @deprecated ICU 60 This API is ICU internal only.
*/
@Deprecated
public abstract void apply(DecimalQuantity value);
//////////////////////////
// PACKAGE-PRIVATE APIS //
//////////////////////////
@ -266,12 +345,10 @@ public abstract class Rounder implements Cloneable {
}
}
abstract void apply(FormatQuantity value);
int chooseMultiplierAndApply(FormatQuantity input, MultiplierProducer producer) {
int chooseMultiplierAndApply(DecimalQuantity input, MultiplierProducer producer) {
// TODO: Make a better and more efficient implementation.
// TODO: Avoid the object creation here.
FormatQuantity copy = input.createCopy();
DecimalQuantity copy = input.createCopy();
assert !input.isZero();
int magnitude = input.getMagnitude();
@ -299,11 +376,11 @@ public abstract class Rounder implements Cloneable {
static class InfiniteRounderImpl extends Rounder {
private InfiniteRounderImpl() {
public InfiniteRounderImpl() {
}
@Override
void apply(FormatQuantity value) {
public void apply(DecimalQuantity value) {
value.roundToInfinity();
value.setFractionLength(0, Integer.MAX_VALUE);
}
@ -313,13 +390,13 @@ public abstract class Rounder implements Cloneable {
final int minFrac;
final int maxFrac;
private FractionRounderImpl(int minFrac, int maxFrac) {
public FractionRounderImpl(int minFrac, int maxFrac) {
this.minFrac = minFrac;
this.maxFrac = maxFrac;
}
@Override
void apply(FormatQuantity value) {
public void apply(DecimalQuantity value) {
value.roundToMagnitude(getRoundingMagnitudeFraction(maxFrac), mathContext);
value.setFractionLength(Math.max(0, -getDisplayMagnitudeFraction(minFrac)), Integer.MAX_VALUE);
}
@ -329,19 +406,19 @@ public abstract class Rounder implements Cloneable {
final int minSig;
final int maxSig;
private SignificantRounderImpl(int minSig, int maxSig) {
public SignificantRounderImpl(int minSig, int maxSig) {
this.minSig = minSig;
this.maxSig = maxSig;
}
@Override
void apply(FormatQuantity value) {
public void apply(DecimalQuantity value) {
value.roundToMagnitude(getRoundingMagnitudeSignificant(value, maxSig), mathContext);
value.setFractionLength(Math.max(0, -getDisplayMagnitudeSignificant(value, minSig)), Integer.MAX_VALUE);
}
/** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */
public void apply(FormatQuantity quantity, int minInt) {
public void apply(DecimalQuantity quantity, int minInt) {
assert quantity.isZero();
quantity.setFractionLength(minSig - minInt, Integer.MAX_VALUE);
}
@ -353,7 +430,7 @@ public abstract class Rounder implements Cloneable {
final int minSig;
final int maxSig;
private FracSigRounderImpl(int minFrac, int maxFrac, int minSig, int maxSig) {
public FracSigRounderImpl(int minFrac, int maxFrac, int minSig, int maxSig) {
this.minFrac = minFrac;
this.maxFrac = maxFrac;
this.minSig = minSig;
@ -361,7 +438,7 @@ public abstract class Rounder implements Cloneable {
}
@Override
void apply(FormatQuantity value) {
public void apply(DecimalQuantity value) {
int displayMag = getDisplayMagnitudeFraction(minFrac);
int roundingMag = getRoundingMagnitudeFraction(maxFrac);
if (minSig == -1) {
@ -381,12 +458,12 @@ public abstract class Rounder implements Cloneable {
static class IncrementRounderImpl extends Rounder {
final BigDecimal increment;
private IncrementRounderImpl(BigDecimal increment) {
public IncrementRounderImpl(BigDecimal increment) {
this.increment = increment;
}
@Override
void apply(FormatQuantity value) {
public void apply(DecimalQuantity value) {
value.roundToIncrement(increment, mathContext);
value.setFractionLength(increment.scale(), increment.scale());
}
@ -395,12 +472,12 @@ public abstract class Rounder implements Cloneable {
static class CurrencyRounderImpl extends CurrencyRounder {
final CurrencyUsage usage;
private CurrencyRounderImpl(CurrencyUsage usage) {
public CurrencyRounderImpl(CurrencyUsage usage) {
this.usage = usage;
}
@Override
void apply(FormatQuantity value) {
public void apply(DecimalQuantity value) {
// Call .withCurrency() before .apply()!
throw new AssertionError();
}
@ -408,11 +485,11 @@ public abstract class Rounder implements Cloneable {
static class PassThroughRounderImpl extends Rounder {
private PassThroughRounderImpl() {
public PassThroughRounderImpl() {
}
@Override
void apply(FormatQuantity value) {
public void apply(DecimalQuantity value) {
// TODO: Assert that value has already been rounded
}
}
@ -424,7 +501,7 @@ public abstract class Rounder implements Cloneable {
return -maxFrac;
}
private static int getRoundingMagnitudeSignificant(FormatQuantity value, int maxSig) {
private static int getRoundingMagnitudeSignificant(DecimalQuantity value, int maxSig) {
if (maxSig == -1) {
return Integer.MIN_VALUE;
}
@ -439,7 +516,7 @@ public abstract class Rounder implements Cloneable {
return -minFrac;
}
private static int getDisplayMagnitudeSignificant(FormatQuantity value, int minSig) {
private static int getDisplayMagnitudeSignificant(DecimalQuantity value, int minSig) {
int magnitude = value.isZero() ? 0 : value.getMagnitude();
return magnitude - minSig + 1;
}

View file

@ -2,7 +2,7 @@
// License & terms of use: http://www.unicode.org/copyright.html#License
package newapi;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.Modifier;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.text.DecimalFormatSymbols;
@ -84,7 +84,7 @@ public class ScientificNotation extends Notation implements Cloneable {
}
@Override
public MicroProps processQuantity(FormatQuantity quantity) {
public MicroProps processQuantity(DecimalQuantity quantity) {
MicroProps micros = parent.processQuantity(quantity);
assert micros.rounding != null;

View file

@ -1,6 +1,6 @@
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
package newapi;
package newapi.impl;
import java.util.EnumMap;
import java.util.Map;
@ -8,7 +8,7 @@ import java.util.Map;
import com.ibm.icu.impl.CurrencyData;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.Modifier;
import com.ibm.icu.impl.number.modifiers.SimpleModifier;
import com.ibm.icu.text.NumberFormat.Field;
@ -18,11 +18,8 @@ import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.ULocale;
import newapi.NumberFormatter.UnitWidth;
import newapi.impl.MeasureData;
import newapi.impl.MicroProps;
import newapi.impl.MicroPropsGenerator;
class LongNameHandler implements MicroPropsGenerator {
public class LongNameHandler implements MicroPropsGenerator {
private final Map<StandardPlural, Modifier> data;
/* unsafe */ PluralRules rules;
@ -98,10 +95,10 @@ class LongNameHandler implements MicroPropsGenerator {
}
@Override
public MicroProps processQuantity(FormatQuantity quantity) {
public MicroProps processQuantity(DecimalQuantity quantity) {
MicroProps micros = parent.processQuantity(quantity);
// TODO: Avoid the copy here?
FormatQuantity copy = quantity.createCopy();
DecimalQuantity copy = quantity.createCopy();
micros.rounding.apply(copy);
micros.modOuter = data.get(copy.getStandardPlural(rules));
return micros;

View file

@ -2,59 +2,64 @@
// License & terms of use: http://www.unicode.org/copyright.html#License
package newapi.impl;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.Modifier;
import com.ibm.icu.text.DecimalFormatSymbols;
import newapi.Grouper;
import newapi.IntegerWidth;
import newapi.NumberFormatter;
import newapi.Rounder;
import newapi.NumberFormatter.DecimalMarkDisplay;
import newapi.NumberFormatter.SignDisplay;
import newapi.Rounder;
public class MicroProps implements Cloneable, MicroPropsGenerator {
// Populated globally:
public SignDisplay sign;
public DecimalFormatSymbols symbols;
public Padder padding;
public DecimalMarkDisplay decimal;
public IntegerWidth integerWidth;
// Populated globally:
public SignDisplay sign;
public DecimalFormatSymbols symbols;
public Padder padding;
public DecimalMarkDisplay decimal;
public IntegerWidth integerWidth;
// Populated by notation/unit:
public Modifier modOuter;
public Modifier modMiddle;
public Modifier modInner;
public Rounder rounding;
public Grouper grouping;
public int multiplier;
public boolean useCurrency;
// Populated by notation/unit:
public Modifier modOuter;
public Modifier modMiddle;
public Modifier modInner;
public Rounder rounding;
public Grouper grouping;
public int multiplier;
public boolean useCurrency;
private final boolean immutable;
private final boolean immutable;
private volatile boolean exhausted;
/**
* @param immutable Whether this MicroProps should behave as an immutable after construction with
* respect to the quantity chain.
*/
public MicroProps(boolean immutable) {
this.immutable = immutable;
}
@Override
public MicroProps processQuantity(FormatQuantity quantity) {
if (immutable) {
return (MicroProps) this.clone();
} else {
return this;
/**
* @param immutable
* Whether this MicroProps should behave as an immutable after construction with respect to the quantity
* chain.
*/
public MicroProps(boolean immutable) {
this.immutable = immutable;
}
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
@Override
public MicroProps processQuantity(DecimalQuantity quantity) {
if (immutable) {
return (MicroProps) this.clone();
} else if (exhausted) {
// Safety check
throw new AssertionError("Cannot re-use a mutable MicroProps in the quantity chain");
} else {
exhausted = true;
return this;
}
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
}
}

View file

@ -2,7 +2,7 @@
// License & terms of use: http://www.unicode.org/copyright.html#License
package newapi.impl;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.DecimalQuantity;
/**
* This interface is used when all number formatting settings, including the locale, are known, except for the quantity
@ -31,7 +31,7 @@ import com.ibm.icu.impl.number.FormatQuantity;
* }
*
* &#64;Override
* public MicroProps processQuantity(FormatQuantity quantity) {
* public MicroProps processQuantity(DecimalQuantity quantity) {
* MicroProps micros = this.parent.processQuantity(quantity);
* // Perform manipulations on micros and/or quantity
* return micros;
@ -44,11 +44,11 @@ import com.ibm.icu.impl.number.FormatQuantity;
*/
public interface MicroPropsGenerator {
/**
* Considers the given {@link FormatQuantity}, optionally mutates it, and returns a {@link MicroProps}.
* Considers the given {@link DecimalQuantity}, optionally mutates it, and returns a {@link MicroProps}.
*
* @param quantity
* The quantity for consideration and optional mutation.
* @return A MicroProps instance resolved for the quantity.
*/
public MicroProps processQuantity(FormatQuantity quantity);
public MicroProps processQuantity(DecimalQuantity quantity);
}

View file

@ -4,7 +4,7 @@ package newapi.impl;
import java.math.BigDecimal;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.DecimalQuantity;
public class MultiplierImpl implements MicroPropsGenerator, Cloneable {
final int magnitudeMultiplier;
@ -34,7 +34,7 @@ public class MultiplierImpl implements MicroPropsGenerator, Cloneable {
}
@Override
public MicroProps processQuantity(FormatQuantity quantity) {
public MicroProps processQuantity(DecimalQuantity quantity) {
MicroProps micros = parent.processQuantity(quantity);
quantity.adjustMagnitude(magnitudeMultiplier);
if (bigDecimalMultiplier != null) {

View file

@ -1,12 +1,12 @@
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
package newapi;
package newapi.impl;
import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.impl.number.AffixPatternUtils;
import com.ibm.icu.impl.number.AffixPatternUtils.SymbolProvider;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.PatternParser;
import com.ibm.icu.impl.number.AffixUtils;
import com.ibm.icu.impl.number.AffixUtils.SymbolProvider;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.Modifier;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.impl.number.modifiers.ConstantMultiFieldModifier;
@ -15,11 +15,9 @@ import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.util.Currency;
import newapi.NumberFormatter;
import newapi.NumberFormatter.SignDisplay;
import newapi.NumberFormatter.UnitWidth;
import newapi.impl.AffixPatternProvider;
import newapi.impl.MicroProps;
import newapi.impl.MicroPropsGenerator;
/**
* This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes in
@ -86,7 +84,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
/**
* Sets a reference to the parsed decimal format pattern, usually obtained from
* {@link PatternParser#parse(String)}, but any implementation of {@link AffixPatternProvider} is accepted.
* {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is accepted.
*/
public void setPatternInfo(AffixPatternProvider patternInfo) {
this.patternInfo = patternInfo;
@ -157,7 +155,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
* This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤").
*/
public boolean needsPlurals() {
return patternInfo.containsSymbolType(AffixPatternUtils.TYPE_CURRENCY_TRIPLE);
return patternInfo.containsSymbolType(AffixUtils.TYPE_CURRENCY_TRIPLE);
}
/**
@ -219,7 +217,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
}
public static interface ImmutableMurkyModifier extends MicroPropsGenerator {
public void applyToMicros(MicroProps micros, FormatQuantity quantity);
public void applyToMicros(MicroProps micros, DecimalQuantity quantity);
}
public static class ImmutableMurkyModifierWithoutPlurals implements ImmutableMurkyModifier {
@ -234,7 +232,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
}
@Override
public MicroProps processQuantity(FormatQuantity quantity) {
public MicroProps processQuantity(DecimalQuantity quantity) {
assert parent != null;
MicroProps micros = parent.processQuantity(quantity);
applyToMicros(micros, quantity);
@ -242,7 +240,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
}
@Override
public void applyToMicros(MicroProps micros, FormatQuantity quantity) {
public void applyToMicros(MicroProps micros, DecimalQuantity quantity) {
if (quantity.isNegative()) {
micros.modMiddle = negative;
} else {
@ -273,7 +271,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
}
@Override
public MicroProps processQuantity(FormatQuantity quantity) {
public MicroProps processQuantity(DecimalQuantity quantity) {
assert parent != null;
MicroProps micros = parent.processQuantity(quantity);
applyToMicros(micros, quantity);
@ -281,9 +279,9 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
}
@Override
public void applyToMicros(MicroProps micros, FormatQuantity quantity) {
public void applyToMicros(MicroProps micros, DecimalQuantity quantity) {
// TODO: Fix this. Avoid the copy.
FormatQuantity copy = quantity.createCopy();
DecimalQuantity copy = quantity.createCopy();
copy.roundToInfinity();
StandardPlural plural = copy.getStandardPlural(rules);
Modifier mod = mods[getModIndex(quantity.isNegative(), plural)];
@ -297,11 +295,11 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
}
@Override
public MicroProps processQuantity(FormatQuantity fq) {
public MicroProps processQuantity(DecimalQuantity fq) {
MicroProps micros = parent.processQuantity(fq);
if (needsPlurals()) {
// TODO: Fix this. Avoid the copy.
FormatQuantity copy = fq.createCopy();
DecimalQuantity copy = fq.createCopy();
micros.rounding.apply(copy);
setNumberProperties(fq.isNegative(), copy.getStandardPlural(rules));
} else {
@ -333,14 +331,14 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
private int insertPrefix(NumberStringBuilder sb, int position) {
enterCharSequenceMode(true);
int length = AffixPatternUtils.unescape(this, sb, position, this);
int length = AffixUtils.unescape(this, sb, position, this);
exitCharSequenceMode();
return length;
}
private int insertSuffix(NumberStringBuilder sb, int position) {
enterCharSequenceMode(false);
int length = AffixPatternUtils.unescape(this, sb, position, this);
int length = AffixUtils.unescape(this, sb, position, this);
exitCharSequenceMode();
return length;
}
@ -348,24 +346,24 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
@Override
public CharSequence getSymbol(int type) {
switch (type) {
case AffixPatternUtils.TYPE_MINUS_SIGN:
case AffixUtils.TYPE_MINUS_SIGN:
return symbols.getMinusSignString();
case AffixPatternUtils.TYPE_PLUS_SIGN:
case AffixUtils.TYPE_PLUS_SIGN:
return symbols.getPlusSignString();
case AffixPatternUtils.TYPE_PERCENT:
case AffixUtils.TYPE_PERCENT:
return symbols.getPercentString();
case AffixPatternUtils.TYPE_PERMILLE:
case AffixUtils.TYPE_PERMILLE:
return symbols.getPerMillString();
case AffixPatternUtils.TYPE_CURRENCY_SINGLE:
case AffixUtils.TYPE_CURRENCY_SINGLE:
// FormatWidth ISO overrides the singular currency symbol
if (unitWidth == UnitWidth.ISO_CODE) {
return currency2;
} else {
return currency1;
}
case AffixPatternUtils.TYPE_CURRENCY_DOUBLE:
case AffixUtils.TYPE_CURRENCY_DOUBLE:
return currency2;
case AffixPatternUtils.TYPE_CURRENCY_TRIPLE:
case AffixUtils.TYPE_CURRENCY_TRIPLE:
// NOTE: This is the code path only for patterns containing "".
// Most plural currencies are formatted in DataUtils.
assert plural != null;
@ -374,9 +372,9 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq
} else {
return currency3[plural.ordinal()];
}
case AffixPatternUtils.TYPE_CURRENCY_QUAD:
case AffixUtils.TYPE_CURRENCY_QUAD:
return "\uFFFD";
case AffixPatternUtils.TYPE_CURRENCY_QUINT:
case AffixUtils.TYPE_CURRENCY_QUINT:
return "\uFFFD";
default:
throw new AssertionError();

View file

@ -27,7 +27,7 @@ import java.util.Map;
import org.junit.Test;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.text.CompactDecimalFormat;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.DecimalFormat;
@ -664,7 +664,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
CompactDecimalFormat cdf = CompactDecimalFormat.getInstance(ULocale.ENGLISH, CompactStyle.SHORT);
cdf.setProperties(new PropertySetter() {
@Override
public void set(Properties props) {
public void set(DecimalFormatProperties props) {
props.setCompactCustomData(customData);
}
});

View file

@ -10,8 +10,9 @@ import org.junit.Test;
import com.ibm.icu.dev.test.TestUtil;
import com.ibm.icu.impl.number.Parse.ParseMode;
import com.ibm.icu.impl.number.PatternAndPropertyUtils;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringUtils;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.DecimalFormat_ICU58;
import com.ibm.icu.util.CurrencyAmount;
@ -423,7 +424,7 @@ public class NumberFormatDataDrivenTest {
}
};
static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, Properties properties) {
static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, DecimalFormatProperties properties) {
if (tuple.minIntegerDigits != null) {
properties.setMinimumIntegerDigits(tuple.minIntegerDigits);
}
@ -509,8 +510,8 @@ public class NumberFormatDataDrivenTest {
}
if (tuple.localizedPattern != null) {
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(tuple.locale);
String converted = PatternAndPropertyUtils.convertLocalized(tuple.localizedPattern, symbols, false);
PatternAndPropertyUtils.parseToExistingProperties(converted, properties);
String converted = PatternStringUtils.convertLocalized(tuple.localizedPattern, symbols, false);
PatternStringParser.parseToExistingProperties(converted, properties);
}
if (tuple.lenient != null) {
properties.setParseMode(tuple.lenient == 0 ? ParseMode.STRICT : ParseMode.LENIENT);
@ -547,12 +548,12 @@ public class NumberFormatDataDrivenTest {
public String format(DataDrivenNumberFormatTestData tuple) {
String pattern = (tuple.pattern == null) ? "0" : tuple.pattern;
ULocale locale = (tuple.locale == null) ? ULocale.ENGLISH : tuple.locale;
Properties properties =
PatternAndPropertyUtils.parseToProperties(
DecimalFormatProperties properties =
PatternStringParser.parseToProperties(
pattern,
tuple.currency != null
? PatternAndPropertyUtils.IGNORE_ROUNDING_ALWAYS
: PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER);
? PatternStringParser.IGNORE_ROUNDING_ALWAYS
: PatternStringParser.IGNORE_ROUNDING_NEVER);
propertiesFromTuple(tuple, properties);
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
LocalizedNumberFormatter fmt = NumberPropertyMapper.create(properties, symbols).locale(locale);

View file

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.Set;
import org.junit.Test;
@ -43,7 +44,7 @@ import com.ibm.icu.impl.ICUConfig;
import com.ibm.icu.impl.LocaleUtility;
import com.ibm.icu.impl.data.ResourceReader;
import com.ibm.icu.impl.data.TokenIterator;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.math.MathContext;
import com.ibm.icu.text.CompactDecimalFormat;
@ -989,8 +990,14 @@ public class NumberFormatTest extends TestFmwk {
@Test
public void TestCurrencyPatterns() {
int i;
Random rnd = new Random(2017);
Locale[] locs = NumberFormat.getAvailableLocales();
for (i=0; i<locs.length; ++i) {
if (rnd.nextDouble() < 0.9) {
// Check a random subset for speed:
// Otherwise, this test takes a large fraction of the entire time.
continue;
}
NumberFormat nf = NumberFormat.getCurrencyInstance(locs[i]);
// Make sure currency formats do not have a variable number
// of fraction digits
@ -5796,7 +5803,7 @@ public class NumberFormatTest extends TestFmwk {
df.setCurrency(Currency.getInstance("USD"));
df.setProperties(new PropertySetter(){
@Override
public void set(Properties props) {
public void set(DecimalFormatProperties props) {
props.setPluralRules(rules);
}
});

View file

@ -7,8 +7,8 @@ import static org.junit.Assert.fail;
import org.junit.Test;
import com.ibm.icu.impl.number.AffixPatternUtils;
import com.ibm.icu.impl.number.AffixPatternUtils.SymbolProvider;
import com.ibm.icu.impl.number.AffixUtils;
import com.ibm.icu.impl.number.AffixUtils.SymbolProvider;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.util.ULocale;
@ -24,26 +24,26 @@ public class AffixPatternUtilsTest {
@Override
public CharSequence getSymbol(int type) {
switch (type) {
case AffixPatternUtils.TYPE_MINUS_SIGN:
case AffixUtils.TYPE_MINUS_SIGN:
return "";
case AffixPatternUtils.TYPE_PLUS_SIGN:
case AffixUtils.TYPE_PLUS_SIGN:
return SYMBOLS.getPlusSignString();
case AffixPatternUtils.TYPE_PERCENT:
case AffixUtils.TYPE_PERCENT:
return SYMBOLS.getPercentString();
case AffixPatternUtils.TYPE_PERMILLE:
case AffixUtils.TYPE_PERMILLE:
return SYMBOLS.getPerMillString();
case AffixPatternUtils.TYPE_CURRENCY_SINGLE:
case AffixUtils.TYPE_CURRENCY_SINGLE:
return "$";
case AffixPatternUtils.TYPE_CURRENCY_DOUBLE:
case AffixUtils.TYPE_CURRENCY_DOUBLE:
return "XXX";
case AffixPatternUtils.TYPE_CURRENCY_TRIPLE:
case AffixUtils.TYPE_CURRENCY_TRIPLE:
return "long name";
case AffixPatternUtils.TYPE_CURRENCY_QUAD:
case AffixUtils.TYPE_CURRENCY_QUAD:
return "\uFFFD";
case AffixPatternUtils.TYPE_CURRENCY_QUINT:
case AffixUtils.TYPE_CURRENCY_QUINT:
// TODO: Add support for narrow currency symbols here.
return "\uFFFD";
case AffixPatternUtils.TYPE_CURRENCY_OVERFLOW:
case AffixUtils.TYPE_CURRENCY_OVERFLOW:
return "\uFFFD";
default:
throw new AssertionError();
@ -72,7 +72,7 @@ public class AffixPatternUtilsTest {
String input = (String) cas[0];
String expected = (String) cas[1];
sb.setLength(0);
AffixPatternUtils.escape(input, sb);
AffixUtils.escape(input, sb);
assertEquals(expected, sb.toString());
}
}
@ -122,8 +122,8 @@ public class AffixPatternUtilsTest {
String output = (String) cas[3];
assertEquals(
"Currency on <" + input + ">", curr, AffixPatternUtils.hasCurrencySymbols(input));
assertEquals("Length on <" + input + ">", length, AffixPatternUtils.estimateLength(input));
"Currency on <" + input + ">", curr, AffixUtils.hasCurrencySymbols(input));
assertEquals("Length on <" + input + ">", length, AffixUtils.estimateLength(input));
String actual = unescapeWithDefaults(input);
assertEquals("Output on <" + input + ">", output, actual);
@ -150,11 +150,11 @@ public class AffixPatternUtilsTest {
assertEquals(
"Contains on input " + input,
hasMinusSign,
AffixPatternUtils.containsType(input, AffixPatternUtils.TYPE_MINUS_SIGN));
AffixUtils.containsType(input, AffixUtils.TYPE_MINUS_SIGN));
assertEquals(
"Replace on input" + input,
output,
AffixPatternUtils.replaceType(input, AffixPatternUtils.TYPE_MINUS_SIGN, '+'));
AffixUtils.replaceType(input, AffixUtils.TYPE_MINUS_SIGN, '+'));
}
}
@ -164,13 +164,13 @@ public class AffixPatternUtilsTest {
for (String str : invalidExamples) {
try {
AffixPatternUtils.hasCurrencySymbols(str);
AffixUtils.hasCurrencySymbols(str);
fail("No exception was thrown on an invalid string");
} catch (IllegalArgumentException e) {
// OK
}
try {
AffixPatternUtils.estimateLength(str);
AffixUtils.estimateLength(str);
fail("No exception was thrown on an invalid string");
} catch (IllegalArgumentException e) {
// OK
@ -208,20 +208,20 @@ public class AffixPatternUtilsTest {
String input = cas[0];
String expected = cas[1];
sb.clear();
AffixPatternUtils.unescape(input, sb, 0, provider);
AffixUtils.unescape(input, sb, 0, provider);
assertEquals("With symbol provider on <" + input + ">", expected, sb.toString());
}
// Test insertion position
sb.clear();
sb.append("abcdefg", null);
AffixPatternUtils.unescape("-+%", sb, 4, provider);
AffixUtils.unescape("-+%", sb, 4, provider);
assertEquals("Symbol provider into middle", "abcd123efg", sb.toString());
}
private static String unescapeWithDefaults(String input) {
NumberStringBuilder nsb = new NumberStringBuilder();
AffixPatternUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER);
AffixUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER);
return nsb.toString();
}
}

View file

@ -13,12 +13,12 @@ import java.util.Random;
import org.junit.Test;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.number.FormatQuantity;
import com.ibm.icu.impl.number.FormatQuantity1;
import com.ibm.icu.impl.number.FormatQuantity2;
import com.ibm.icu.impl.number.FormatQuantity3;
import com.ibm.icu.impl.number.FormatQuantity4;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.DecimalQuantity_SimpleStorage;
import com.ibm.icu.impl.number.DecimalQuantity_64BitBCD;
import com.ibm.icu.impl.number.DecimalQuantity_ByteArrayBCD;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.util.ULocale;
@ -27,34 +27,34 @@ import newapi.LocalizedNumberFormatter;
import newapi.NumberPropertyMapper;
/** TODO: This is a temporary name for this class. Suggestions for a better name? */
public class FormatQuantityTest extends TestFmwk {
public class DecimalQuantityTest extends TestFmwk {
@Test
public void testBehavior() throws ParseException {
// Make a list of several formatters to test the behavior of FormatQuantity.
// Make a list of several formatters to test the behavior of DecimalQuantity.
List<LocalizedNumberFormatter> formats = new ArrayList<LocalizedNumberFormatter>();
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
Properties properties = new Properties();
DecimalFormatProperties properties = new DecimalFormatProperties();
formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH));
properties =
new Properties()
new DecimalFormatProperties()
.setMinimumSignificantDigits(3)
.setMaximumSignificantDigits(3)
.setCompactStyle(CompactStyle.LONG);
formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH));
properties =
new Properties()
new DecimalFormatProperties()
.setMinimumExponentDigits(1)
.setMaximumIntegerDigits(3)
.setMaximumFractionDigits(1);
formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH));
properties = new Properties().setRoundingIncrement(new BigDecimal("0.5"));
properties = new DecimalFormatProperties().setRoundingIncrement(new BigDecimal("0.5"));
formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH));
String[] cases = {
@ -99,68 +99,68 @@ public class FormatQuantityTest extends TestFmwk {
int i = 0;
for (String str : cases) {
testFormatQuantity(i++, str, formats, 0);
testDecimalQuantity(i++, str, formats, 0);
}
i = 0;
for (String str : hardCases) {
testFormatQuantity(i++, str, formats, 1);
testDecimalQuantity(i++, str, formats, 1);
}
i = 0;
for (String str : doubleCases) {
testFormatQuantity(i++, str, formats, 2);
testDecimalQuantity(i++, str, formats, 2);
}
}
static void testFormatQuantity(int t, String str, List<LocalizedNumberFormatter> formats, int mode) {
static void testDecimalQuantity(int t, String str, List<LocalizedNumberFormatter> formats, int mode) {
if (mode == 2) {
assertEquals("Double is not valid", Double.toString(Double.parseDouble(str)), str);
}
List<FormatQuantity> qs = new ArrayList<FormatQuantity>();
List<DecimalQuantity> qs = new ArrayList<DecimalQuantity>();
BigDecimal d = new BigDecimal(str);
qs.add(new FormatQuantity1(d));
if (mode == 0) qs.add(new FormatQuantity2(d));
qs.add(new FormatQuantity3(d));
qs.add(new FormatQuantity4(d));
qs.add(new DecimalQuantity_SimpleStorage(d));
if (mode == 0) qs.add(new DecimalQuantity_64BitBCD(d));
qs.add(new DecimalQuantity_ByteArrayBCD(d));
qs.add(new DecimalQuantity_DualStorageBCD(d));
if (new BigDecimal(Double.toString(d.doubleValue())).compareTo(d) == 0) {
double dv = d.doubleValue();
qs.add(new FormatQuantity1(dv));
if (mode == 0) qs.add(new FormatQuantity2(dv));
qs.add(new FormatQuantity3(dv));
qs.add(new FormatQuantity4(dv));
qs.add(new DecimalQuantity_SimpleStorage(dv));
if (mode == 0) qs.add(new DecimalQuantity_64BitBCD(dv));
qs.add(new DecimalQuantity_ByteArrayBCD(dv));
qs.add(new DecimalQuantity_DualStorageBCD(dv));
}
if (new BigDecimal(Long.toString(d.longValue())).compareTo(d) == 0) {
double lv = d.longValue();
qs.add(new FormatQuantity1(lv));
if (mode == 0) qs.add(new FormatQuantity2(lv));
qs.add(new FormatQuantity3(lv));
qs.add(new FormatQuantity4(lv));
qs.add(new DecimalQuantity_SimpleStorage(lv));
if (mode == 0) qs.add(new DecimalQuantity_64BitBCD(lv));
qs.add(new DecimalQuantity_ByteArrayBCD(lv));
qs.add(new DecimalQuantity_DualStorageBCD(lv));
}
testFormatQuantityExpectedOutput(qs.get(0), str);
testDecimalQuantityExpectedOutput(qs.get(0), str);
if (qs.size() == 1) {
return;
}
for (int i = 1; i < qs.size(); i++) {
FormatQuantity q0 = qs.get(0);
FormatQuantity q1 = qs.get(i);
testFormatQuantityExpectedOutput(q1, str);
testFormatQuantityRounding(q0, q1);
testFormatQuantityRoundingInterval(q0, q1);
testFormatQuantityMath(q0, q1);
testFormatQuantityWithFormats(q0, q1, formats);
DecimalQuantity q0 = qs.get(0);
DecimalQuantity q1 = qs.get(i);
testDecimalQuantityExpectedOutput(q1, str);
testDecimalQuantityRounding(q0, q1);
testDecimalQuantityRoundingInterval(q0, q1);
testDecimalQuantityMath(q0, q1);
testDecimalQuantityWithFormats(q0, q1, formats);
}
}
private static void testFormatQuantityExpectedOutput(FormatQuantity rq, String expected) {
private static void testDecimalQuantityExpectedOutput(DecimalQuantity rq, String expected) {
StringBuilder sb = new StringBuilder();
FormatQuantity q0 = rq.createCopy();
DecimalQuantity q0 = rq.createCopy();
// Force an accurate double
q0.roundToInfinity();
q0.setIntegerLength(1, Integer.MAX_VALUE);
@ -182,68 +182,68 @@ public class FormatQuantityTest extends TestFmwk {
private static final MathContext MATH_CONTEXT_PRECISION =
new MathContext(3, RoundingMode.HALF_UP);
private static void testFormatQuantityRounding(FormatQuantity rq0, FormatQuantity rq1) {
FormatQuantity q0 = rq0.createCopy();
FormatQuantity q1 = rq1.createCopy();
private static void testDecimalQuantityRounding(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
q0.roundToMagnitude(-1, MATH_CONTEXT_HALF_EVEN);
q1.roundToMagnitude(-1, MATH_CONTEXT_HALF_EVEN);
testFormatQuantityBehavior(q0, q1);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.roundToMagnitude(-1, MATH_CONTEXT_CEILING);
q1.roundToMagnitude(-1, MATH_CONTEXT_CEILING);
testFormatQuantityBehavior(q0, q1);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.roundToMagnitude(-1, MATH_CONTEXT_PRECISION);
q1.roundToMagnitude(-1, MATH_CONTEXT_PRECISION);
testFormatQuantityBehavior(q0, q1);
testDecimalQuantityBehavior(q0, q1);
}
private static void testFormatQuantityRoundingInterval(FormatQuantity rq0, FormatQuantity rq1) {
FormatQuantity q0 = rq0.createCopy();
FormatQuantity q1 = rq1.createCopy();
private static void testDecimalQuantityRoundingInterval(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
q0.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_HALF_EVEN);
q1.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_HALF_EVEN);
testFormatQuantityBehavior(q0, q1);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_CEILING);
q1.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_CEILING);
testFormatQuantityBehavior(q0, q1);
testDecimalQuantityBehavior(q0, q1);
}
private static void testFormatQuantityMath(FormatQuantity rq0, FormatQuantity rq1) {
FormatQuantity q0 = rq0.createCopy();
FormatQuantity q1 = rq1.createCopy();
private static void testDecimalQuantityMath(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
q0.adjustMagnitude(-3);
q1.adjustMagnitude(-3);
testFormatQuantityBehavior(q0, q1);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.multiplyBy(new BigDecimal("3.14159"));
q1.multiplyBy(new BigDecimal("3.14159"));
testFormatQuantityBehavior(q0, q1);
testDecimalQuantityBehavior(q0, q1);
}
private static void testFormatQuantityWithFormats(
FormatQuantity rq0, FormatQuantity rq1, List<LocalizedNumberFormatter> formats) {
private static void testDecimalQuantityWithFormats(
DecimalQuantity rq0, DecimalQuantity rq1, List<LocalizedNumberFormatter> formats) {
for (LocalizedNumberFormatter format : formats) {
FormatQuantity q0 = rq0.createCopy();
FormatQuantity q1 = rq1.createCopy();
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
String s1 = format.format(q0).toString();
String s2 = format.format(q1).toString();
assertEquals("Different output from formatter (" + q0 + ", " + q1 + ")", s1, s2);
}
}
private static void testFormatQuantityBehavior(FormatQuantity rq0, FormatQuantity rq1) {
FormatQuantity q0 = rq0.createCopy();
FormatQuantity q1 = rq1.createCopy();
private static void testDecimalQuantityBehavior(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
assertEquals("Different sign (" + q0 + ", " + q1 + ")", q0.isNegative(), q1.isNegative());
@ -279,19 +279,19 @@ public class FormatQuantityTest extends TestFmwk {
q1.getDigit(m));
}
if (rq0 instanceof FormatQuantity4) {
String message = ((FormatQuantity4) rq0).checkHealth();
if (rq0 instanceof DecimalQuantity_DualStorageBCD) {
String message = ((DecimalQuantity_DualStorageBCD) rq0).checkHealth();
if (message != null) errln(message);
}
if (rq1 instanceof FormatQuantity4) {
String message = ((FormatQuantity4) rq1).checkHealth();
if (rq1 instanceof DecimalQuantity_DualStorageBCD) {
String message = ((DecimalQuantity_DualStorageBCD) rq1).checkHealth();
if (message != null) errln(message);
}
}
@Test
public void testSwitchStorage() {
FormatQuantity4 fq = new FormatQuantity4();
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
fq.setToLong(1234123412341234L);
assertFalse("Should not be using byte array", fq.usingBytes());
@ -311,7 +311,7 @@ public class FormatQuantityTest extends TestFmwk {
@Test
public void testAppend() {
FormatQuantity4 fq = new FormatQuantity4();
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
fq.appendDigit((byte) 1, 0, true);
assertBigDecimalEquals("Failed on append", "1.", fq.toBigDecimal());
assertNull("Failed health check", fq.checkHealth());
@ -401,15 +401,15 @@ public class FormatQuantityTest extends TestFmwk {
checkDoubleBehavior(d, false, "");
}
assertEquals("NaN check failed", Double.NaN, new FormatQuantity4(Double.NaN).toDouble());
assertEquals("NaN check failed", Double.NaN, new DecimalQuantity_DualStorageBCD(Double.NaN).toDouble());
assertEquals(
"Inf check failed",
Double.POSITIVE_INFINITY,
new FormatQuantity4(Double.POSITIVE_INFINITY).toDouble());
new DecimalQuantity_DualStorageBCD(Double.POSITIVE_INFINITY).toDouble());
assertEquals(
"-Inf check failed",
Double.NEGATIVE_INFINITY,
new FormatQuantity4(Double.NEGATIVE_INFINITY).toDouble());
new DecimalQuantity_DualStorageBCD(Double.NEGATIVE_INFINITY).toDouble());
// Generate random doubles
String alert = "UNEXPECTED FAILURE: PLEASE REPORT THIS MESSAGE TO THE ICU TEAM: ";
@ -422,7 +422,7 @@ public class FormatQuantityTest extends TestFmwk {
}
private static void checkDoubleBehavior(double d, boolean explicitRequired, String alert) {
FormatQuantity4 fq = new FormatQuantity4(d);
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(d);
if (explicitRequired)
assertTrue(alert + "Should be using approximate double", !fq.explicitExactDouble);
assertEquals(alert + "Initial construction from hard double", d, fq.toDouble());
@ -459,7 +459,7 @@ public class FormatQuantityTest extends TestFmwk {
MathContext mc = (MathContext) cas[2];
boolean usesExact = (Boolean) cas[3];
FormatQuantity4 fq = new FormatQuantity4(d);
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(d);
assertTrue("Should be using approximate double", !fq.explicitExactDouble);
fq.roundToMagnitude(-maxFrac, mc);
assertEquals(

View file

@ -6,22 +6,22 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.ibm.icu.impl.number.PatternParser;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.ULocale;
import newapi.MutablePatternModifier;
import newapi.NumberFormatter.SignDisplay;
import newapi.NumberFormatter.UnitWidth;
import newapi.impl.MutablePatternModifier;
public class MurkyModifierTest {
@Test
public void basic() {
MutablePatternModifier murky = new MutablePatternModifier(false);
murky.setPatternInfo(PatternParser.parse("a0b"));
murky.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b"));
murky.setPatternAttributes(SignDisplay.AUTO, false);
murky.setSymbols(
DecimalFormatSymbols.getInstance(ULocale.ENGLISH),
@ -41,7 +41,7 @@ public class MurkyModifierTest {
assertEquals("a", getPrefix(murky));
assertEquals("b", getSuffix(murky));
murky.setPatternInfo(PatternParser.parse("a0b;c-0d"));
murky.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"));
murky.setPatternAttributes(SignDisplay.AUTO, false);
murky.setNumberProperties(false, null);
assertEquals("a", getPrefix(murky));

View file

@ -11,6 +11,7 @@ import java.util.Locale;
import org.junit.Ignore;
import org.junit.Test;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.NumberingSystem;
import com.ibm.icu.util.Currency;
@ -30,7 +31,6 @@ import newapi.NumberFormatter;
import newapi.NumberFormatter.DecimalMarkDisplay;
import newapi.NumberFormatter.SignDisplay;
import newapi.NumberFormatter.UnitWidth;
import newapi.NumberPropertyMapper;
import newapi.Rounder;
import newapi.UnlocalizedNumberFormatter;
import newapi.impl.Padder;
@ -397,8 +397,11 @@ public class NumberFormatterTest {
assertFormatSingle(
"Currency Long Name from Pattern Syntax",
"$GBP F0 grouping=none integer-width=1- symbols=loc:en_US sign=AUTO decimal=AUTO",
NumberPropertyMapper.create("0 ¤¤¤", DecimalFormatSymbols.getInstance()).unit(GBP),
"$GBP F0 grouping=none integer-width=1- symbols=loc:en sign=AUTO decimal=AUTO",
NumberFormatter.fromDecimalFormat(
PatternStringParser.parseToProperties("0 ¤¤¤"),
DecimalFormatSymbols.getInstance(ULocale.ENGLISH),
null).unit(GBP),
ULocale.ENGLISH,
1234567.89,
"1234568 British pounds");
@ -658,7 +661,7 @@ public class NumberFormatterTest {
assertFormatDescending(
"Rounding None",
"Y",
NumberFormatter.with().rounding(Rounder.none()),
NumberFormatter.with().rounding(Rounder.unlimited()),
ULocale.ENGLISH,
"87,650",
"8,765",
@ -1229,8 +1232,8 @@ public class NumberFormatterTest {
@Test
public void getPrefixSuffix() {
Object[][] cases = {
{ NumberFormatter.withLocale(ULocale.ENGLISH).unit(GBP).unitWidth(UnitWidth.ISO_CODE), "GBP", "", "-GBP",
"" },
{ NumberFormatter.withLocale(ULocale.ENGLISH).unit(GBP).unitWidth(UnitWidth.ISO_CODE), "GBP", "",
"-GBP", "" },
{ NumberFormatter.withLocale(ULocale.ENGLISH).unit(GBP).unitWidth(UnitWidth.FULL_NAME), "",
" British pounds", "-", " British pounds" } };

View file

@ -7,8 +7,9 @@ import static org.junit.Assert.fail;
import org.junit.Test;
import com.ibm.icu.impl.number.PatternAndPropertyUtils;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringUtils;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.util.ULocale;
@ -27,8 +28,8 @@ public class PatternStringTest {
String localized = ".'ab'c'b''a'''#,##0a0b'a%'";
String toStandard = "+-'ab'c'b''a'''#,##0.0%'a%'";
assertEquals(localized, PatternAndPropertyUtils.convertLocalized(standard, symbols, true));
assertEquals(toStandard, PatternAndPropertyUtils.convertLocalized(localized, symbols, false));
assertEquals(localized, PatternStringUtils.convertLocalized(standard, symbols, true));
assertEquals(toStandard, PatternStringUtils.convertLocalized(localized, symbols, false));
}
@Test
@ -60,8 +61,8 @@ public class PatternStringTest {
String input = cas[0];
String output = cas[1];
Properties properties = PatternAndPropertyUtils.parseToProperties(input);
String actual = PatternAndPropertyUtils.propertiesToString(properties);
DecimalFormatProperties properties = PatternStringParser.parseToProperties(input);
String actual = PatternStringUtils.propertiesToPatternString(properties);
assertEquals(
"Failed on input pattern '" + input + "', properties " + properties, output, actual);
}
@ -70,27 +71,27 @@ public class PatternStringTest {
@Test
public void testToPatternWithProperties() {
Object[][] cases = {
{new Properties().setPositivePrefix("abc"), "abc#"},
{new Properties().setPositiveSuffix("abc"), "#abc"},
{new Properties().setPositivePrefixPattern("abc"), "abc#"},
{new Properties().setPositiveSuffixPattern("abc"), "#abc"},
{new Properties().setNegativePrefix("abc"), "#;abc#"},
{new Properties().setNegativeSuffix("abc"), "#;#abc"},
{new Properties().setNegativePrefixPattern("abc"), "#;abc#"},
{new Properties().setNegativeSuffixPattern("abc"), "#;#abc"},
{new Properties().setPositivePrefix("+"), "'+'#"},
{new Properties().setPositivePrefixPattern("+"), "+#"},
{new Properties().setPositivePrefix("+'"), "'+'''#"},
{new Properties().setPositivePrefix("'+"), "'''+'#"},
{new Properties().setPositivePrefix("'"), "''#"},
{new Properties().setPositivePrefixPattern("+''"), "+''#"},
{new DecimalFormatProperties().setPositivePrefix("abc"), "abc#"},
{new DecimalFormatProperties().setPositiveSuffix("abc"), "#abc"},
{new DecimalFormatProperties().setPositivePrefixPattern("abc"), "abc#"},
{new DecimalFormatProperties().setPositiveSuffixPattern("abc"), "#abc"},
{new DecimalFormatProperties().setNegativePrefix("abc"), "#;abc#"},
{new DecimalFormatProperties().setNegativeSuffix("abc"), "#;#abc"},
{new DecimalFormatProperties().setNegativePrefixPattern("abc"), "#;abc#"},
{new DecimalFormatProperties().setNegativeSuffixPattern("abc"), "#;#abc"},
{new DecimalFormatProperties().setPositivePrefix("+"), "'+'#"},
{new DecimalFormatProperties().setPositivePrefixPattern("+"), "+#"},
{new DecimalFormatProperties().setPositivePrefix("+'"), "'+'''#"},
{new DecimalFormatProperties().setPositivePrefix("'+"), "'''+'#"},
{new DecimalFormatProperties().setPositivePrefix("'"), "''#"},
{new DecimalFormatProperties().setPositivePrefixPattern("+''"), "+''#"},
};
for (Object[] cas : cases) {
Properties input = (Properties) cas[0];
DecimalFormatProperties input = (DecimalFormatProperties) cas[0];
String output = (String) cas[1];
String actual = PatternAndPropertyUtils.propertiesToString(input);
String actual = PatternStringUtils.propertiesToPatternString(input);
assertEquals("Failed on input properties " + input, output, actual);
}
}
@ -103,7 +104,7 @@ public class PatternStringTest {
for (String pattern : invalidPatterns) {
try {
PatternAndPropertyUtils.parseToProperties(pattern);
PatternStringParser.parseToProperties(pattern);
fail("Didn't throw IllegalArgumentException when parsing pattern: " + pattern);
} catch (IllegalArgumentException e) {
}
@ -112,8 +113,8 @@ public class PatternStringTest {
@Test
public void testBug13117() {
Properties expected = PatternAndPropertyUtils.parseToProperties("0");
Properties actual = PatternAndPropertyUtils.parseToProperties("0;");
DecimalFormatProperties expected = PatternStringParser.parseToProperties("0");
DecimalFormatProperties actual = PatternStringParser.parseToProperties("0;");
assertEquals("Should not consume negative subpattern", expected, actual);
}
}

View file

@ -31,8 +31,8 @@ import org.junit.Test;
import com.ibm.icu.dev.test.serializable.SerializableTestUtility;
import com.ibm.icu.impl.number.Parse.GroupingMode;
import com.ibm.icu.impl.number.Parse.ParseMode;
import com.ibm.icu.impl.number.PatternAndPropertyUtils;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.ThingsNeedingNewHome.PadPosition;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.CurrencyPluralInfo;
@ -47,8 +47,8 @@ public class PropertiesTest {
@Test
public void testBasicEquals() {
Properties p1 = new Properties();
Properties p2 = new Properties();
DecimalFormatProperties p1 = new DecimalFormatProperties();
DecimalFormatProperties p2 = new DecimalFormatProperties();
assertEquals(p1, p2);
p1.setPositivePrefix("abc");
@ -61,14 +61,14 @@ public class PropertiesTest {
@Test
public void testFieldCoverage() {
Properties p0 = new Properties();
Properties p1 = new Properties();
Properties p2 = new Properties();
Properties p3 = new Properties();
Properties p4 = new Properties();
DecimalFormatProperties p0 = new DecimalFormatProperties();
DecimalFormatProperties p1 = new DecimalFormatProperties();
DecimalFormatProperties p2 = new DecimalFormatProperties();
DecimalFormatProperties p3 = new DecimalFormatProperties();
DecimalFormatProperties p4 = new DecimalFormatProperties();
Set<Integer> hashCodes = new HashSet<Integer>();
Field[] fields = Properties.class.getDeclaredFields();
Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
@ -81,7 +81,7 @@ public class PropertiesTest {
String setterName = "set" + fieldNamePascalCase;
Method getter, setter;
try {
getter = Properties.class.getMethod(getterName);
getter = DecimalFormatProperties.class.getMethod(getterName);
assertEquals(
"Getter does not return correct type", field.getType(), getter.getReturnType());
} catch (NoSuchMethodException e) {
@ -92,10 +92,10 @@ public class PropertiesTest {
continue;
}
try {
setter = Properties.class.getMethod(setterName, field.getType());
setter = DecimalFormatProperties.class.getMethod(setterName, field.getType());
assertEquals(
"Method " + setterName + " does not return correct type",
Properties.class,
DecimalFormatProperties.class,
setter.getReturnType());
} catch (NoSuchMethodException e) {
fail("Could not find method " + setterName + " for field " + field);
@ -157,7 +157,7 @@ public class PropertiesTest {
hashCodes.add(p1.hashCode());
// Check for clone behavior
Properties copy = p1.clone();
DecimalFormatProperties copy = p1.clone();
assertEquals("Field " + field + " did not get copied in clone", p1, copy);
assertEquals(p1.hashCode(), copy.hashCode());
assertEquals(getter.invoke(p1), getter.invoke(copy));
@ -307,10 +307,10 @@ public class PropertiesTest {
@Test
public void TestBasicSerializationRoundTrip() throws IOException, ClassNotFoundException {
Properties props0 = new Properties();
DecimalFormatProperties props0 = new DecimalFormatProperties();
// Write values to some of the fields
PatternAndPropertyUtils.parseToExistingProperties("A-**####,#00.00#b¤", props0);
PatternStringParser.parseToExistingProperties("A-**####,#00.00#b¤", props0);
// Write to byte stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@ -324,7 +324,7 @@ public class PropertiesTest {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
Object obj = ois.readObject();
ois.close();
Properties props1 = (Properties) obj;
DecimalFormatProperties props1 = (DecimalFormatProperties) obj;
// Test equality
assertEquals("Did not round-trip through serialization", props0, props1);
@ -336,9 +336,9 @@ public class PropertiesTest {
@Override
public Object[] getTestObjects() {
return new Object[] {
new Properties(),
PatternAndPropertyUtils.parseToProperties("x#,##0.00%"),
new Properties().setCompactStyle(CompactStyle.LONG).setMinimumExponentDigits(2)
new DecimalFormatProperties(),
PatternStringParser.parseToProperties("x#,##0.00%"),
new DecimalFormatProperties().setCompactStyle(CompactStyle.LONG).setMinimumExponentDigits(2)
};
}