* }
* </pre>
*/
-public class AffixPatternUtils {
+public class AffixUtils {
private static final int STATE_BASE = 0;
private static final int STATE_FIRST_QUOTE = 1;
/**
* 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.
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;
/| or #equals(), but it will NOT catch if you forget to add it to #hashCode(). |/
/+--------------------------------------------------------------------------------------------*/
- public Properties() {
+ public DecimalFormatProperties() {
clear();
}
*
* @return The property bag, for chaining.
*/
- private Properties _clear() {
+ private DecimalFormatProperties _clear() {
compactCustomData = null;
compactStyle = null;
currency = null;
return this;
}
- private Properties _copyFrom(Properties other) {
+ private DecimalFormatProperties _copyFrom(DecimalFormatProperties other) {
compactCustomData = other.compactCustomData;
compactStyle = other.compactStyle;
currency = other.currency;
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);
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);
* @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);
}
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 ///
// 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;
* @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;
* @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;
}
* @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;
}
* @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) {
* @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;
}
* @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;
}
* @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;
}
* @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;
}
* @see #setPadPosition
* @see #setPadString
*/
- public Properties setFormatWidth(int paddingWidth) {
+ public DecimalFormatProperties setFormatWidth(int paddingWidth) {
this.formatWidth = paddingWidth;
return this;
}
* @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;
}
* @return The property bag, for chaining.
* @see #setMultiplier
*/
- public Properties setMagnitudeMultiplier(int magnitudeMultiplier) {
+ public DecimalFormatProperties setMagnitudeMultiplier(int magnitudeMultiplier) {
this.magnitudeMultiplier = magnitudeMultiplier;
return this;
}
* @see MathContext
* @see #setRoundingMode
*/
- public Properties setMathContext(MathContext mathContext) {
+ public DecimalFormatProperties setMathContext(MathContext mathContext) {
this.mathContext = mathContext;
return this;
}
* @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;
}
* @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;
}
* @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;
}
* @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;
}
* @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;
}
* enabling grouping.
* @return The property bag, for chaining.
*/
- public Properties setMinimumGroupingDigits(int minimumGroupingDigits) {
+ public DecimalFormatProperties setMinimumGroupingDigits(int minimumGroupingDigits) {
this.minimumGroupingDigits = minimumGroupingDigits;
return this;
}
* @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;
}
* @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;
}
* @return The property bag, for chaining.
* @see #setMagnitudeMultiplier
*/
- public Properties setMultiplier(BigDecimal multiplier) {
+ public DecimalFormatProperties setMultiplier(BigDecimal multiplier) {
this.multiplier = multiplier;
return this;
}
* @see PositiveNegativeAffixFormat
* @see #setNegativePrefixPattern
*/
- public Properties setNegativePrefix(String negativePrefix) {
+ public DecimalFormatProperties setNegativePrefix(String negativePrefix) {
this.negativePrefix = negativePrefix;
return this;
}
* @see PositiveNegativeAffixFormat
* @see #setNegativePrefix
*/
- public Properties setNegativePrefixPattern(String negativePrefixPattern) {
+ public DecimalFormatProperties setNegativePrefixPattern(String negativePrefixPattern) {
this.negativePrefixPattern = negativePrefixPattern;
return this;
}
* @see PositiveNegativeAffixFormat
* @see #setNegativeSuffixPattern
*/
- public Properties setNegativeSuffix(String negativeSuffix) {
+ public DecimalFormatProperties setNegativeSuffix(String negativeSuffix) {
this.negativeSuffix = negativeSuffix;
return this;
}
* @see PositiveNegativeAffixFormat
* @see #setNegativeSuffix
*/
- public Properties setNegativeSuffixPattern(String negativeSuffixPattern) {
+ public DecimalFormatProperties setNegativeSuffixPattern(String negativeSuffixPattern) {
this.negativeSuffixPattern = negativeSuffixPattern;
return this;
}
* @return The property bag, for chaining.
* @see #setFormatWidth
*/
- public Properties setPadPosition(PadPosition paddingLocation) {
+ public DecimalFormatProperties setPadPosition(PadPosition paddingLocation) {
this.padPosition = paddingLocation;
return this;
}
* @return The property bag, for chaining.
* @see #setFormatWidth
*/
- public Properties setPadString(String paddingString) {
+ public DecimalFormatProperties setPadString(String paddingString) {
this.padString = paddingString;
return this;
}
* @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;
}
* @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;
}
* fraction parts
* @return The property bag, for chaining.
*/
- public Properties setParseIntegerOnly(boolean parseIntegerOnly) {
+ public DecimalFormatProperties setParseIntegerOnly(boolean parseIntegerOnly) {
this.parseIntegerOnly = parseIntegerOnly;
return this;
}
* @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;
}
* @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;
}
* BigInteger when possible.
* @return The property bag, for chaining.
*/
- public Properties setParseToBigDecimal(boolean parseToBigDecimal) {
+ public DecimalFormatProperties setParseToBigDecimal(boolean parseToBigDecimal) {
this.parseToBigDecimal = parseToBigDecimal;
return this;
}
* @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;
}
* @see PositiveNegativeAffixFormat
* @see #setPositivePrefixPattern
*/
- public Properties setPositivePrefix(String positivePrefix) {
+ public DecimalFormatProperties setPositivePrefix(String positivePrefix) {
this.positivePrefix = positivePrefix;
return this;
}
* @see PositiveNegativeAffixFormat
* @see #setPositivePrefix
*/
- public Properties setPositivePrefixPattern(String positivePrefixPattern) {
+ public DecimalFormatProperties setPositivePrefixPattern(String positivePrefixPattern) {
this.positivePrefixPattern = positivePrefixPattern;
return this;
}
* @see PositiveNegativeAffixFormat
* @see #setPositiveSuffixPattern
*/
- public Properties setPositiveSuffix(String positiveSuffix) {
+ public DecimalFormatProperties setPositiveSuffix(String positiveSuffix) {
this.positiveSuffix = positiveSuffix;
return this;
}
* @see PositiveNegativeAffixFormat
* @see #setPositiveSuffix
*/
- public Properties setPositiveSuffixPattern(String positiveSuffixPattern) {
+ public DecimalFormatProperties setPositiveSuffixPattern(String positiveSuffixPattern) {
this.positiveSuffixPattern = positiveSuffixPattern;
return this;
}
* @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;
}
* @see RoundingMode
* @see #setMathContext
*/
- public Properties setRoundingMode(RoundingMode roundingMode) {
+ public DecimalFormatProperties setRoundingMode(RoundingMode roundingMode) {
this.roundingMode = roundingMode;
return this;
}
* @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;
}
* @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;
}
* surrounded by <Properties>.
*/
public void toStringBare(StringBuilder result) {
- Field[] fields = Properties.class.getDeclaredFields();
+ Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
for (Field field : fields) {
Object myValue, defaultValue;
try {
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;
* <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.
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.
/**
* 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();
*/
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();
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.
*
*
* @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();
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
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);
}
}
@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,
/**
* 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
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.
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;
isApproximate = other.isApproximate;
}
- public FormatQuantityBCD clear() {
+ public DecimalQuantity_AbstractBCD clear() {
lOptPos = Integer.MAX_VALUE;
lReqPos = 0;
rReqPos = 0;
@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;
@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;
}
@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());
}
}
/**
- * 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.
*
/**
* 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.
*/
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
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
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);
}
}
@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);
}
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,
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
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) {
}
@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);
}
/**
- * 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
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,
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
return Integer.MAX_VALUE;
}
- public FormatQuantity1(long input) {
+ public DecimalQuantity_SimpleStorage(long input) {
if (input < 0) {
setNegative(true);
input *= -1;
}
/**
- * 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;
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;
}
}
- public FormatQuantity1(BigDecimal decimal) {
+ public DecimalQuantity_SimpleStorage(BigDecimal decimal) {
setToBigDecimal(decimal);
}
- public FormatQuantity1(FormatQuantity1 other) {
+ public DecimalQuantity_SimpleStorage(DecimalQuantity_SimpleStorage other) {
copyFrom(other);
}
}
@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;
}
}
- /** @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;
}
/**
- * 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.
*
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;
}
/**
- * 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() {
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();
@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();
@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(":");
// 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
}
/**
- * @see Parse#parse(String, ParsePosition, ParseMode, boolean, boolean, Properties,
+ * @see Parse#parse(String, ParsePosition, ParseMode, boolean, boolean, DecimalFormatProperties,
* DecimalFormatSymbols)
*/
private static enum StateName {
int score;
// Numerical value:
- FormatQuantity4 fq = new FormatQuantity4();
+ DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
int numDigits;
int trailingZeros;
int exponent;
*
* @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;
*
* @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);
sb.append("{");
sb.append(currentAffixPattern);
sb.append(":");
- sb.append(AffixPatternUtils.getOffset(currentStepwiseParserTag) - 1);
+ sb.append(AffixUtils.getOffset(currentStepwiseParserTag) - 1);
sb.append("}");
}
sb.append(" ");
int prevLength;
// Properties and Symbols memory:
- Properties properties;
+ DecimalFormatProperties properties;
DecimalFormatSymbols symbols;
ParseMode mode;
boolean caseSensitive;
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);
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()) {
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;
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) {
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;
}
}
- 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.
}
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);
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();
CharSequence input,
ParsePosition ppos,
boolean parseCurrency,
- Properties properties,
+ DecimalFormatProperties properties,
DecimalFormatSymbols symbols) {
if (input == null || ppos == null || properties == null || symbols == null) {
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++) {
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:
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
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;
nextTypeOrCp =
isString
? Character.codePointAt(str, (int) nextOffsetOrTag)
- : AffixPatternUtils.getTypeOrCp(nextOffsetOrTag);
+ : AffixUtils.getTypeOrCp(nextOffsetOrTag);
if (!isIgnorable(nextTypeOrCp, state)) break;
}
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;
nextTypeOrCp =
isString
? Character.codePointAt(str, (int) nextOffsetOrTag)
- : AffixPatternUtils.getTypeOrCp(nextOffsetOrTag);
+ : AffixUtils.getTypeOrCp(nextOffsetOrTag);
if (!isIgnorable(nextTypeOrCp, state)) break;
}
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);
}
/**
- * 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;
@Override
public boolean containsSymbolType(int type) {
- return AffixPatternUtils.containsType(pattern, type);
+ return AffixUtils.containsType(pattern, type);
}
}
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;
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);
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;
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);
+ }
+ }
}
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.
* 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
// Prefixes
if (ppp != null)
sb.append(ppp);
- AffixPatternUtils.escape(pp, sb);
+ AffixUtils.escape(pp, sb);
int afterPrefixPos = sb.length();
// Figure out the grouping sizes.
int beforeSuffixPos = sb.length();
if (psp != null)
sb.append(psp);
- AffixPatternUtils.escape(ps, sb);
+ AffixUtils.escape(ps, sb);
// Resolve Padding
if (paddingWidth != -1) {
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;
}
}
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();
* <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
* 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;
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);
- }
- }
}
* @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();
* @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();
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;
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();
}
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;
import newapi.FormattedNumber;
import newapi.LocalizedNumberFormatter;
import newapi.NumberFormatter;
-import newapi.NumberPropertyMapper;
-import newapi.impl.MacroProps;
import newapi.impl.Padder.PadPosition;
/**
* 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
* 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 //
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();
}
*/
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();
}
*/
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();
}
/** 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
|| 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();
}
* @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);
* @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);
}
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;
}
// 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;
if (symbols == null) {
symbols = getDefaultSymbols();
}
- exportedProperties = new Properties();
+ exportedProperties = new DecimalFormatProperties();
refreshFormatter();
}
}
*/
@Override
public Number parse(String text, ParsePosition parsePosition) {
- Properties pprops = threadLocalProperties.get();
+ DecimalFormatProperties pprops = threadLocalProperties.get();
synchronized (this) {
pprops.copyFrom(properties);
}
@Override
public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosition) {
try {
- Properties pprops = threadLocalProperties.get();
+ DecimalFormatProperties pprops = threadLocalProperties.get();
synchronized (this) {
pprops.copyFrom(properties);
}
// 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);
}
/**
*/
public synchronized String toLocalizedPattern() {
String pattern = toPattern();
- return PatternAndPropertyUtils.convertLocalized(pattern, symbols, true);
+ return PatternStringUtils.convertLocalized(pattern, symbols, true);
}
/**
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();
}
};
// 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
locale = symbols.getULocale();
}
assert locale != null;
- formatter = NumberFormatter.with().macros(macros).locale(locale);
+ formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedProperties).locale(locale);
}
/**
* 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()));
}
/**
* @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);
}
/**
* @deprecated This API is ICU internal only.
*/
@Deprecated
- public void set(Properties props);
+ public void set(DecimalFormatProperties props);
}
/**
import java.text.ParsePosition;
-import com.ibm.icu.impl.number.FormatQuantity4;
+import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
//===================================================================
// NFSubstitution (abstract base class)
// (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;
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);
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 {
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;
}
@Override
- public MicroProps processQuantity(FormatQuantity input) {
+ public MicroProps processQuantity(DecimalQuantity input) {
MicroProps micros = parent.processQuantity(input);
assert micros.rounding != null;
// 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;
}
*
* <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.
*
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;
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;
// 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 {
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"
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;
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) {
* @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);
}
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();
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);
+ }
}
// 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;
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 {
-
- public static Worker1 fromMacros(MacroProps macros) {
+/**
+ * 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 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);
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;
String innerPattern = null;
LongNameHandler longNames = null;
- Rounder defaultRounding = Rounder.none();
+ Rounder defaultRounding = Rounder.unlimited();
Currency currency = DEFAULT_CURRENCY;
UnitWidth unitWidth = null;
boolean perMille = false;
}
// 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) {
//////////
/**
- * 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) {
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);
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++) {
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++) {
// 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) {
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;
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);
}
* 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.
* 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();
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());
@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
@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);
}
}
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()));
}
}
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;
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);
}
}
+ /**
+ * 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);
}
}
+ /**
+ * 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);
}
}
+ /**
+ * 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);
}
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);
}
}
+ /**
+ * @internal
+ * @deprecated ICU 60 This API is ICU internal only.
+ */
+ @Deprecated
+ public abstract void apply(DecimalQuantity value);
+
//////////////////////////
// PACKAGE-PRIVATE APIS //
//////////////////////////
}
}
- 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();
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);
}
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);
}
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);
}
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;
}
@Override
- void apply(FormatQuantity value) {
+ public void apply(DecimalQuantity value) {
int displayMag = getDisplayMagnitudeFraction(minFrac);
int roundingMag = getRoundingMagnitudeFraction(maxFrac);
if (minSig == -1) {
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());
}
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();
}
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
}
}
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;
}
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;
}
// 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;
}
@Override
- public MicroProps processQuantity(FormatQuantity quantity) {
+ public MicroProps processQuantity(DecimalQuantity quantity) {
MicroProps micros = parent.processQuantity(quantity);
assert micros.rounding != null;
// © 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;
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;
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;
}
@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;
// 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 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;
-
- /**
- * @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;
+ // 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;
+
+ 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(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);
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
}
- }
}
// 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
* }
*
* @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;
*/
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);
}
\ No newline at end of file
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;
}
@Override
- public MicroProps processQuantity(FormatQuantity quantity) {
+ public MicroProps processQuantity(DecimalQuantity quantity) {
MicroProps micros = parent.processQuantity(quantity);
quantity.adjustMagnitude(magnitudeMultiplier);
if (bigDecimalMultiplier != null) {
// © 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;
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
/**
* 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;
* 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);
}
/**
}
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 {
}
@Override
- public MicroProps processQuantity(FormatQuantity quantity) {
+ public MicroProps processQuantity(DecimalQuantity quantity) {
assert parent != null;
MicroProps micros = parent.processQuantity(quantity);
applyToMicros(micros, quantity);
}
@Override
- public void applyToMicros(MicroProps micros, FormatQuantity quantity) {
+ public void applyToMicros(MicroProps micros, DecimalQuantity quantity) {
if (quantity.isNegative()) {
micros.modMiddle = negative;
} else {
}
@Override
- public MicroProps processQuantity(FormatQuantity quantity) {
+ public MicroProps processQuantity(DecimalQuantity quantity) {
assert parent != null;
MicroProps micros = parent.processQuantity(quantity);
applyToMicros(micros, quantity);
}
@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)];
}
@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 {
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;
}
@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;
} 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();
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;
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);
}
});
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;
}
};
- static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, Properties properties) {
+ static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, DecimalFormatProperties properties) {
if (tuple.minIntegerDigits != null) {
properties.setMinimumIntegerDigits(tuple.minIntegerDigits);
}
}
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);
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);
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Random;
import java.util.Set;
import org.junit.Test;
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;
@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
df.setCurrency(Currency.getInstance("USD"));
df.setProperties(new PropertySetter(){
@Override
- public void set(Properties props) {
+ public void set(DecimalFormatProperties props) {
props.setPluralRules(rules);
}
});
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;
@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();
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());
}
}
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);
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, '+'));
}
}
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
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();
}
}
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;
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 = {
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);
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());
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());
@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());
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: ";
}
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());
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(
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),
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));
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;
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;
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");
assertFormatDescending(
"Rounding None",
"Y",
- NumberFormatter.with().rounding(Rounder.none()),
+ NumberFormatter.with().rounding(Rounder.unlimited()),
ULocale.ENGLISH,
"87,650",
"8,765",
@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" } };
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;
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
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);
}
@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);
}
}
for (String pattern : invalidPatterns) {
try {
- PatternAndPropertyUtils.parseToProperties(pattern);
+ PatternStringParser.parseToProperties(pattern);
fail("Didn't throw IllegalArgumentException when parsing pattern: " + pattern);
} catch (IllegalArgumentException e) {
}
@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);
}
}
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;
@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");
@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;
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) {
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);
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));
@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();
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);
@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)
};
}