Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1332)

Unified Diff: main/classes/core/src/com/ibm/icu/impl/number/PatternString.java

Issue 329960043: ticket:13177 NumberFormat2 from Shane's branch Base URL: svn+ssh://source.icu-project.org/repos/icu/trunk/icu4j/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: main/classes/core/src/com/ibm/icu/impl/number/PatternString.java
===================================================================
--- main/classes/core/src/com/ibm/icu/impl/number/PatternString.java (revision 40289)
+++ main/classes/core/src/com/ibm/icu/impl/number/PatternString.java (working copy)
@@ -8,6 +8,8 @@
import com.ibm.icu.impl.number.formatters.PaddingFormat.PadPosition;
import com.ibm.icu.text.DecimalFormatSymbols;
+import newapi.impl.AffixPatternProvider;
+
/**
* Handles parsing and creation of the compact pattern string representation of a decimal format.
*/
@@ -26,7 +28,7 @@
*/
public static Properties parseToProperties(String pattern, int ignoreRounding) {
Properties properties = new Properties();
- LdmlDecimalPatternParser.parse(pattern, properties, ignoreRounding);
+ parse(pattern, properties, ignoreRounding);
return properties;
}
@@ -50,7 +52,7 @@
*/
public static void parseToExistingProperties(
String pattern, Properties properties, int ignoreRounding) {
- LdmlDecimalPatternParser.parse(pattern, properties, ignoreRounding);
+ parse(pattern, properties, ignoreRounding);
}
public static void parseToExistingProperties(String pattern, Properties properties) {
@@ -431,487 +433,187 @@
public static final int IGNORE_ROUNDING_IF_CURRENCY = 1;
public static final int IGNORE_ROUNDING_ALWAYS = 2;
- /** Implements a recursive descent parser for decimal format patterns. */
- static class LdmlDecimalPatternParser {
+ 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;
+ }
- /**
- * An internal, intermediate data structure used for storing parse results before they are
- * finalized into a DecimalFormatPattern.Builder.
- */
- private static class PatternParseResult {
- SubpatternParseResult positive = new SubpatternParseResult();
- SubpatternParseResult negative = null;
+ // TODO: Use whitespace characters from PatternProps
+ // TODO: Use thread locals here.
+ LdmlPatternInfo.PatternParseResult result = LdmlPatternInfo.parse(pattern);
+ saveToProperties(properties, result, ignoreRounding);
+ }
- /** Finalizes the temporary data stored in the PatternParseResult to the Builder. */
- void saveToProperties(Properties properties, int _ignoreRounding) {
- // Translate from PatternState to Properties.
- // Note that most data from "negative" is ignored per the specification of DecimalFormat.
+ /** Finalizes the temporary data stored in the PatternParseResult to the Builder. */
+ private static void saveToProperties(
+ Properties properties, LdmlPatternInfo.PatternParseResult ppr, int _ignoreRounding) {
+ // Translate from PatternParseResult to Properties.
+ // Note that most data from "negative" is ignored per the specification of DecimalFormat.
- 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;
- }
+ LdmlPatternInfo.SubpatternParseResult positive = ppr.positive;
+ LdmlPatternInfo.SubpatternParseResult negative = ppr.negative;
+ String pattern = ppr.pattern;
- // Grouping settings
- if (positive.groupingSizes[1] != -1) {
- properties.setGroupingSize(positive.groupingSizes[0]);
- } else {
- properties.setGroupingSize(Properties.DEFAULT_GROUPING_SIZE);
- }
- if (positive.groupingSizes[2] != -1) {
- properties.setSecondaryGroupingSize(positive.groupingSizes[1]);
- } else {
- properties.setSecondaryGroupingSize(Properties.DEFAULT_SECONDARY_GROUPING_SIZE);
- }
-
- // For backwards compatibility, require that the pattern emit at least one min digit.
- int minInt, minFrac;
- if (positive.totalIntegerDigits == 0 && positive.maximumFractionDigits > 0) {
- // patterns like ".##"
- minInt = 0;
- minFrac = Math.max(1, positive.minimumFractionDigits);
- } else if (positive.minimumIntegerDigits == 0 && positive.minimumFractionDigits == 0) {
- // patterns like "#.##"
- minInt = 1;
- minFrac = 0;
- } else {
- minInt = positive.minimumIntegerDigits;
- minFrac = positive.minimumFractionDigits;
- }
-
- // Rounding settings
- // Don't set basic rounding when there is a currency sign; defer to CurrencyUsage
- if (positive.minimumSignificantDigits > 0) {
- properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
- properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
- properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
- properties.setMinimumSignificantDigits(positive.minimumSignificantDigits);
- properties.setMaximumSignificantDigits(positive.maximumSignificantDigits);
- } else if (!positive.rounding.isZero()) {
- if (!ignoreRounding) {
- properties.setMinimumFractionDigits(minFrac);
- properties.setMaximumFractionDigits(positive.maximumFractionDigits);
- properties.setRoundingIncrement(positive.rounding.toBigDecimal());
- } else {
- properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
- properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
- properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
- }
- properties.setMinimumSignificantDigits(Properties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS);
- properties.setMaximumSignificantDigits(Properties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS);
- } else {
- if (!ignoreRounding) {
- properties.setMinimumFractionDigits(minFrac);
- properties.setMaximumFractionDigits(positive.maximumFractionDigits);
- properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
- } else {
- properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
- properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
- properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
- }
- properties.setMinimumSignificantDigits(Properties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS);
- properties.setMaximumSignificantDigits(Properties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS);
- }
-
- // If the pattern ends with a '.' then force the decimal point.
- if (positive.hasDecimal && positive.maximumFractionDigits == 0) {
- properties.setDecimalSeparatorAlwaysShown(true);
- } else {
- properties.setDecimalSeparatorAlwaysShown(false);
- }
-
- // Scientific notation settings
- if (positive.exponentDigits > 0) {
- properties.setExponentSignAlwaysShown(positive.exponentShowPlusSign);
- properties.setMinimumExponentDigits(positive.exponentDigits);
- if (positive.minimumSignificantDigits == 0) {
- // patterns without '@' can define max integer digits, used for engineering notation
- properties.setMinimumIntegerDigits(positive.minimumIntegerDigits);
- properties.setMaximumIntegerDigits(positive.totalIntegerDigits);
- } else {
- // patterns with '@' cannot define max integer digits
- properties.setMinimumIntegerDigits(1);
- properties.setMaximumIntegerDigits(Properties.DEFAULT_MAXIMUM_INTEGER_DIGITS);
- }
- } else {
- properties.setExponentSignAlwaysShown(Properties.DEFAULT_EXPONENT_SIGN_ALWAYS_SHOWN);
- properties.setMinimumExponentDigits(Properties.DEFAULT_MINIMUM_EXPONENT_DIGITS);
- properties.setMinimumIntegerDigits(minInt);
- properties.setMaximumIntegerDigits(Properties.DEFAULT_MAXIMUM_INTEGER_DIGITS);
- }
-
- // Padding settings
- if (positive.padding.length() > 0) {
- // The width of the positive prefix and suffix templates are included in the padding
- int paddingWidth =
- positive.paddingWidth
- + AffixPatternUtils.unescapedLength(positive.prefix)
- + AffixPatternUtils.unescapedLength(positive.suffix);
- properties.setFormatWidth(paddingWidth);
- if (positive.padding.length() == 1) {
- properties.setPadString(positive.padding.toString());
- } else if (positive.padding.length() == 2) {
- if (positive.padding.charAt(0) == '\'') {
- properties.setPadString("'");
- } else {
- properties.setPadString(positive.padding.toString());
- }
- } else {
- properties.setPadString(
- positive.padding.subSequence(1, positive.padding.length() - 1).toString());
- }
- assert positive.paddingLocation != null;
- properties.setPadPosition(positive.paddingLocation);
- } else {
- properties.setFormatWidth(Properties.DEFAULT_FORMAT_WIDTH);
- properties.setPadString(Properties.DEFAULT_PAD_STRING);
- properties.setPadPosition(Properties.DEFAULT_PAD_POSITION);
- }
-
- // 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(positive.prefix.toString());
- properties.setPositiveSuffixPattern(positive.suffix.toString());
- if (negative != null) {
- properties.setNegativePrefixPattern(negative.prefix.toString());
- properties.setNegativeSuffixPattern(negative.suffix.toString());
- } 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(Properties.DEFAULT_MAGNITUDE_MULTIPLIER);
- }
- }
+ 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;
}
- private static class SubpatternParseResult {
- int[] groupingSizes = new int[] {0, -1, -1};
- int minimumIntegerDigits = 0;
- int totalIntegerDigits = 0;
- int minimumFractionDigits = 0;
- int maximumFractionDigits = 0;
- int minimumSignificantDigits = 0;
- int maximumSignificantDigits = 0;
- boolean hasDecimal = false;
- int paddingWidth = 0;
- PadPosition paddingLocation = null;
- FormatQuantity4 rounding = new FormatQuantity4();
- boolean exponentShowPlusSign = false;
- int exponentDigits = 0;
- boolean hasPercentSign = false;
- boolean hasPerMilleSign = false;
- boolean hasCurrencySign = false;
-
- StringBuilder padding = new StringBuilder();
- StringBuilder prefix = new StringBuilder();
- StringBuilder suffix = new StringBuilder();
+ // 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(Properties.DEFAULT_GROUPING_SIZE);
}
-
- /** An internal class used for tracking the cursor during parsing of a pattern string. */
- private static class ParserState {
- final String pattern;
- int offset;
-
- ParserState(String pattern) {
- this.pattern = pattern;
- this.offset = 0;
- }
-
- int peek() {
- if (offset == pattern.length()) {
- return -1;
- } else {
- return pattern.codePointAt(offset);
- }
- }
-
- int next() {
- int codePoint = peek();
- offset += Character.charCount(codePoint);
- return codePoint;
- }
-
- IllegalArgumentException toParseException(String message) {
- StringBuilder sb = new StringBuilder();
- sb.append("Malformed pattern for ICU DecimalFormat: \"");
- sb.append(pattern);
- sb.append("\": ");
- sb.append(message);
- sb.append(" at position ");
- sb.append(offset);
- return new IllegalArgumentException(sb.toString());
- }
+ if (grouping3 != -1) {
+ properties.setSecondaryGroupingSize(grouping2);
+ } else {
+ properties.setSecondaryGroupingSize(Properties.DEFAULT_SECONDARY_GROUPING_SIZE);
}
- 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 whitespace characters from PatternProps
- // TODO: Use thread locals here.
- ParserState state = new ParserState(pattern);
- PatternParseResult result = new PatternParseResult();
- consumePattern(state, result);
- result.saveToProperties(properties, ignoreRounding);
+ // For backwards compatibility, require that the pattern emit at least one min digit.
+ int minInt, minFrac;
+ if (positive.totalIntegerDigits == 0 && positive.maximumFractionDigits > 0) {
+ // patterns like ".##"
+ minInt = 0;
+ minFrac = Math.max(1, positive.minimumFractionDigits);
+ } else if (positive.minimumIntegerDigits == 0 && positive.minimumFractionDigits == 0) {
+ // patterns like "#.##"
+ minInt = 1;
+ minFrac = 0;
+ } else {
+ minInt = positive.minimumIntegerDigits;
+ minFrac = positive.minimumFractionDigits;
}
- private static void consumePattern(ParserState state, PatternParseResult result) {
- // pattern := subpattern (';' subpattern)?
- consumeSubpattern(state, result.positive);
- if (state.peek() == ';') {
- state.next(); // consume the ';'
- // Don't consume the negative subpattern if it is empty (trailing ';')
- if (state.peek() != -1) {
- result.negative = new SubpatternParseResult();
- consumeSubpattern(state, result.negative);
- }
+ // Rounding settings
+ // Don't set basic rounding when there is a currency sign; defer to CurrencyUsage
+ if (positive.minimumSignificantDigits > 0) {
+ properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
+ properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
+ properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
+ properties.setMinimumSignificantDigits(positive.minimumSignificantDigits);
+ properties.setMaximumSignificantDigits(positive.maximumSignificantDigits);
+ } else if (positive.rounding != null) {
+ if (!ignoreRounding) {
+ properties.setMinimumFractionDigits(minFrac);
+ properties.setMaximumFractionDigits(positive.maximumFractionDigits);
+ properties.setRoundingIncrement(
+ positive.rounding.toBigDecimal().setScale(positive.minimumFractionDigits));
+ } else {
+ properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
+ properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
+ properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
}
- if (state.peek() != -1) {
- throw state.toParseException("Found unquoted special character");
+ properties.setMinimumSignificantDigits(Properties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS);
+ properties.setMaximumSignificantDigits(Properties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS);
+ } else {
+ if (!ignoreRounding) {
+ properties.setMinimumFractionDigits(minFrac);
+ properties.setMaximumFractionDigits(positive.maximumFractionDigits);
+ properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
+ } else {
+ properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
+ properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
+ properties.setRoundingIncrement(Properties.DEFAULT_ROUNDING_INCREMENT);
}
+ properties.setMinimumSignificantDigits(Properties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS);
+ properties.setMaximumSignificantDigits(Properties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS);
}
- private static void consumeSubpattern(ParserState state, SubpatternParseResult result) {
- // subpattern := literals? number exponent? literals?
- consumePadding(state, result, PadPosition.BEFORE_PREFIX);
- consumeAffix(state, result, result.prefix);
- consumePadding(state, result, PadPosition.AFTER_PREFIX);
- consumeFormat(state, result);
- consumeExponent(state, result);
- consumePadding(state, result, PadPosition.BEFORE_SUFFIX);
- consumeAffix(state, result, result.suffix);
- consumePadding(state, result, PadPosition.AFTER_SUFFIX);
+ // If the pattern ends with a '.' then force the decimal point.
+ if (positive.hasDecimal && positive.maximumFractionDigits == 0) {
+ properties.setDecimalSeparatorAlwaysShown(true);
+ } else {
+ properties.setDecimalSeparatorAlwaysShown(false);
}
- private static void consumePadding(
- ParserState state, SubpatternParseResult result, PadPosition paddingLocation) {
- if (state.peek() != '*') {
- return;
+ // Scientific notation settings
+ if (positive.exponentDigits > 0) {
+ properties.setExponentSignAlwaysShown(positive.exponentShowPlusSign);
+ properties.setMinimumExponentDigits(positive.exponentDigits);
+ if (positive.minimumSignificantDigits == 0) {
+ // patterns without '@' can define max integer digits, used for engineering notation
+ properties.setMinimumIntegerDigits(positive.minimumIntegerDigits);
+ properties.setMaximumIntegerDigits(positive.totalIntegerDigits);
+ } else {
+ // patterns with '@' cannot define max integer digits
+ properties.setMinimumIntegerDigits(1);
+ properties.setMaximumIntegerDigits(Properties.DEFAULT_MAXIMUM_INTEGER_DIGITS);
}
- result.paddingLocation = paddingLocation;
- state.next(); // consume the '*'
- consumeLiteral(state, result.padding);
+ } else {
+ properties.setExponentSignAlwaysShown(Properties.DEFAULT_EXPONENT_SIGN_ALWAYS_SHOWN);
+ properties.setMinimumExponentDigits(Properties.DEFAULT_MINIMUM_EXPONENT_DIGITS);
+ properties.setMinimumIntegerDigits(minInt);
+ properties.setMaximumIntegerDigits(Properties.DEFAULT_MAXIMUM_INTEGER_DIGITS);
}
- private static void consumeAffix(
- ParserState state, SubpatternParseResult result, StringBuilder destination) {
- // literals := { literal }
- while (true) {
- switch (state.peek()) {
- case '#':
- case '@':
- case ';':
- case '*':
- case '.':
- case ',':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case -1:
- // Characters that cannot appear unquoted in a literal
- return;
+ // Compute the affix patterns (required for both padding and affixes)
+ String posPrefix = ppr.getString(AffixPatternProvider.Flags.PREFIX);
+ String posSuffix = ppr.getString(0);
- case '%':
- result.hasPercentSign = true;
- break;
-
- case '‰':
- result.hasPerMilleSign = true;
- break;
-
- case '¤':
- result.hasCurrencySign = true;
- break;
+ // Padding settings
+ if (positive.paddingEndpoints != 0) {
+ // The width of the positive prefix and suffix templates are included in the padding
+ int paddingWidth =
+ positive.paddingWidth
+ + AffixPatternUtils.unescapedLength(posPrefix)
+ + AffixPatternUtils.unescapedLength(posSuffix);
+ properties.setFormatWidth(paddingWidth);
+ String rawPaddingString = ppr.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);
}
- consumeLiteral(state, destination);
- }
- }
-
- private static void consumeLiteral(ParserState state, StringBuilder destination) {
- if (state.peek() == -1) {
- throw state.toParseException("Expected unquoted literal but found EOL");
- } else if (state.peek() == '\'') {
- destination.appendCodePoint(state.next()); // consume the starting quote
- while (state.peek() != '\'') {
- if (state.peek() == -1) {
- throw state.toParseException("Expected quoted literal but found EOL");
- } else {
- destination.appendCodePoint(state.next()); // consume a quoted character
- }
- }
- destination.appendCodePoint(state.next()); // consume the ending quote
} else {
- // consume a non-quoted literal character
- destination.appendCodePoint(state.next());
+ properties.setPadString(rawPaddingString.substring(1, rawPaddingString.length() - 1));
}
+ assert positive.paddingLocation != null;
+ properties.setPadPosition(positive.paddingLocation);
+ } else {
+ properties.setFormatWidth(Properties.DEFAULT_FORMAT_WIDTH);
+ properties.setPadString(Properties.DEFAULT_PAD_STRING);
+ properties.setPadPosition(Properties.DEFAULT_PAD_POSITION);
}
- private static void consumeFormat(ParserState state, SubpatternParseResult result) {
- consumeIntegerFormat(state, result);
- if (state.peek() == '.') {
- state.next(); // consume the decimal point
- result.hasDecimal = true;
- result.paddingWidth += 1;
- consumeFractionFormat(state, result);
- }
+ // 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(
+ ppr.getString(
+ AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN | AffixPatternProvider.Flags.PREFIX));
+ properties.setNegativeSuffixPattern(
+ ppr.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN));
+ } else {
+ properties.setNegativePrefixPattern(null);
+ properties.setNegativeSuffixPattern(null);
}
- private static void consumeIntegerFormat(ParserState state, SubpatternParseResult result) {
- boolean seenSignificantDigitMarker = false;
- boolean seenDigit = false;
-
- outer:
- while (true) {
- switch (state.peek()) {
- case ',':
- result.paddingWidth += 1;
- result.groupingSizes[2] = result.groupingSizes[1];
- result.groupingSizes[1] = result.groupingSizes[0];
- result.groupingSizes[0] = 0;
- break;
-
- case '#':
- if (seenDigit) throw state.toParseException("# cannot follow 0 before decimal point");
- result.paddingWidth += 1;
- result.groupingSizes[0] += 1;
- result.totalIntegerDigits += (seenSignificantDigitMarker ? 0 : 1);
- // no change to result.minimumIntegerDigits
- // no change to result.minimumSignificantDigits
- result.maximumSignificantDigits += (seenSignificantDigitMarker ? 1 : 0);
- result.rounding.appendDigit((byte) 0, 0, true);
- break;
-
- case '@':
- seenSignificantDigitMarker = true;
- if (seenDigit) throw state.toParseException("Cannot mix 0 and @");
- result.paddingWidth += 1;
- result.groupingSizes[0] += 1;
- result.totalIntegerDigits += 1;
- // no change to result.minimumIntegerDigits
- result.minimumSignificantDigits += 1;
- result.maximumSignificantDigits += 1;
- result.rounding.appendDigit((byte) 0, 0, true);
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- seenDigit = true;
- if (seenSignificantDigitMarker) throw state.toParseException("Cannot mix @ and 0");
- // TODO: Crash here if we've seen the significant digit marker? See NumberFormatTestCases.txt
- result.paddingWidth += 1;
- result.groupingSizes[0] += 1;
- result.totalIntegerDigits += 1;
- result.minimumIntegerDigits += 1;
- // no change to result.minimumSignificantDigits
- // no change to result.maximumSignificantDigits
- result.rounding.appendDigit((byte) (state.peek() - '0'), 0, true);
- break;
-
- default:
- break outer;
- }
- state.next(); // consume the symbol
- }
-
- // Disallow patterns with a trailing ',' or with two ',' next to each other
- if (result.groupingSizes[0] == 0 && result.groupingSizes[1] != -1) {
- throw state.toParseException("Trailing grouping separator is invalid");
- }
- if (result.groupingSizes[1] == 0 && result.groupingSizes[2] != -1) {
- throw state.toParseException("Grouping width of zero is invalid");
- }
+ // Set the magnitude multiplier
+ if (positive.hasPercentSign) {
+ properties.setMagnitudeMultiplier(2);
+ } else if (positive.hasPerMilleSign) {
+ properties.setMagnitudeMultiplier(3);
+ } else {
+ properties.setMagnitudeMultiplier(Properties.DEFAULT_MAGNITUDE_MULTIPLIER);
}
-
- private static void consumeFractionFormat(ParserState state, SubpatternParseResult result) {
- int zeroCounter = 0;
- boolean seenHash = false;
- while (true) {
- switch (state.peek()) {
- case '#':
- seenHash = true;
- result.paddingWidth += 1;
- // no change to result.minimumFractionDigits
- result.maximumFractionDigits += 1;
- zeroCounter++;
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (seenHash) throw state.toParseException("0 cannot follow # after decimal point");
- result.paddingWidth += 1;
- result.minimumFractionDigits += 1;
- result.maximumFractionDigits += 1;
- if (state.peek() == '0') {
- zeroCounter++;
- } else {
- result.rounding.appendDigit((byte) (state.peek() - '0'), zeroCounter, false);
- zeroCounter = 0;
- }
- break;
-
- default:
- return;
- }
- state.next(); // consume the symbol
- }
- }
-
- private static void consumeExponent(ParserState state, SubpatternParseResult result) {
- if (state.peek() != 'E') {
- return;
- }
- state.next(); // consume the E
- result.paddingWidth++;
- if (state.peek() == '+') {
- state.next(); // consume the +
- result.exponentShowPlusSign = true;
- result.paddingWidth++;
- }
- while (state.peek() == '0') {
- state.next(); // consume the 0
- result.exponentDigits += 1;
- result.paddingWidth++;
- }
- }
}
}

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b