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

Unified Diff: icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java

Issue 315420043: DecimalFormat rewrite, Java Base URL: svn+icussh://source.icu-project.org/repos/icu/branches/shane/numberformat/
Patch Set: r39857: Last commit before merge to trunk. Created 7 years 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: icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java
===================================================================
--- icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java (revision 0)
+++ icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java (revision 39857)
@@ -0,0 +1,227 @@
+// © 2017 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
+package com.ibm.icu.impl.number.formatters;
+
+import com.ibm.icu.impl.number.Format;
+import com.ibm.icu.impl.number.FormatQuantity;
+import com.ibm.icu.impl.number.NumberStringBuilder;
+import com.ibm.icu.impl.number.Properties;
+import com.ibm.icu.text.DecimalFormatSymbols;
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.text.NumberFormat.Field;
+
+public class PositiveDecimalFormat implements Format.TargetFormat {
+
+ public static interface IProperties extends CurrencyFormat.IProperties {
+
+ static int DEFAULT_GROUPING_SIZE = -1;
+
+ /** @see #setGroupingSize */
+ public int getGroupingSize();
+
+ /**
+ * Sets the number of digits between grouping separators. For example, the <em>en-US</em> locale
+ * uses a grouping size of 3, so the number 1234567 would be formatted as "1,234,567". For
+ * locales whose grouping sizes vary with magnitude, see {@link #setSecondaryGroupingSize(int)}.
+ *
+ * @param groupingSize The primary grouping size.
+ * @return The property bag, for chaining.
+ */
+ public IProperties setGroupingSize(int groupingSize);
+
+ static int DEFAULT_SECONDARY_GROUPING_SIZE = -1;
+
+ /** @see #setSecondaryGroupingSize */
+ public int getSecondaryGroupingSize();
+
+ /**
+ * Sets the number of digits between grouping separators higher than the least-significant
+ * grouping separator. For example, the locale <em>hi</em> uses a primary grouping size of 3 and
+ * a secondary grouping size of 2, so the number 1234567 would be formatted as "12,34,567".
+ *
+ * <p>The two levels of grouping separators can be specified in the pattern string. For example,
+ * the <em>hi</em> locale's default decimal format pattern is "#,##,##0.###".
+ *
+ * @param secondaryGroupingSize The secondary grouping size.
+ * @return The property bag, for chaining.
+ */
+ public IProperties setSecondaryGroupingSize(int secondaryGroupingSize);
+
+ static boolean DEFAULT_DECIMAL_SEPARATOR_ALWAYS_SHOWN = false;
+
+ /** @see #setDecimalSeparatorAlwaysShown */
+ public boolean getDecimalSeparatorAlwaysShown();
+
+ /**
+ * Sets whether to always show the decimal point, even if the number doesn't require one. For
+ * example, if always show decimal is true, the number 123 would be formatted as "123." in
+ * locale <em>en-US</em>.
+ *
+ * @param decimalSeparatorAlwaysShown Whether to show the decimal point when it is optional.
+ * @return The property bag, for chaining.
+ */
+ public IProperties setDecimalSeparatorAlwaysShown(boolean decimalSeparatorAlwaysShown);
+
+ static int DEFAULT_MINIMUM_GROUPING_DIGITS = 1;
+
+ /** @see #setMinimumGroupingDigits */
+ public int getMinimumGroupingDigits();
+
+ /**
+ * Sets the minimum number of digits required to be beyond the first grouping separator in order
+ * to enable grouping. For example, if the minimum grouping digits is 2, then 1234 would be
+ * formatted as "1234" but 12345 would be formatted as "12,345" in <em>en-US</em>. Note that
+ * 1234567 would still be formatted as "1,234,567", not "1234,567".
+ *
+ * @param minimumGroupingDigits How many digits must appear before a grouping separator before
+ * enabling grouping.
+ * @return The property bag, for chaining.
+ */
+ public IProperties setMinimumGroupingDigits(int minimumGroupingDigits);
+ }
+
+ public static boolean useGrouping(IProperties properties) {
+ return properties.getGroupingSize() != IProperties.DEFAULT_GROUPING_SIZE
+ || properties.getSecondaryGroupingSize() != IProperties.DEFAULT_SECONDARY_GROUPING_SIZE;
+ }
+
+ public static boolean allowsDecimalPoint(IProperties properties) {
+ return properties.getDecimalSeparatorAlwaysShown() || properties.getMaximumFractionDigits() != 0;
+ }
+
+ // Properties
+ private final boolean alwaysShowDecimal;
+ private final int groupingSize;
+ private final int secondaryGroupingSize;
+ private final int minimumGroupingDigits;
+
+ // Symbols
+ private final String infinityString;
+ private final String nanString;
+ private final String groupingSeparator;
+ private final String decimalSeparator;
+ private final String[] digitStrings;
+ private final int codePointZero;
+
+ public PositiveDecimalFormat(DecimalFormatSymbols symbols, IProperties properties) {
+ groupingSize =
+ (properties.getGroupingSize() < 0)
+ ? properties.getSecondaryGroupingSize()
+ : properties.getGroupingSize();
+ secondaryGroupingSize =
+ (properties.getSecondaryGroupingSize() < 0)
+ ? properties.getGroupingSize()
+ : properties.getSecondaryGroupingSize();
+
+ minimumGroupingDigits = properties.getMinimumGroupingDigits();
+ alwaysShowDecimal = properties.getDecimalSeparatorAlwaysShown();
+ infinityString = symbols.getInfinity();
+ nanString = symbols.getNaN();
+
+ if (CurrencyFormat.useCurrency(properties)) {
+ groupingSeparator = symbols.getMonetaryGroupingSeparatorString();
+ decimalSeparator = symbols.getMonetaryDecimalSeparatorString();
+ } else {
+ groupingSeparator = symbols.getGroupingSeparatorString();
+ decimalSeparator = symbols.getDecimalSeparatorString();
+ }
+
+ // Check to see if we can use code points instead of strings (~15% format performance boost)
+ int _codePointZero = -1;
+ String[] _digitStrings = symbols.getDigitStringsLocal();
+ for (int i = 0; i < _digitStrings.length; i++) {
+ int cp = Character.codePointAt(_digitStrings[i], 0);
+ int cc = Character.charCount(cp);
+ if (cc != _digitStrings[i].length()) {
+ _codePointZero = -1;
+ break;
+ } else if (i == 0) {
+ _codePointZero = cp;
+ } else if (cp != _codePointZero + i) {
+ _codePointZero = -1;
+ break;
+ }
+ }
+ if (_codePointZero != -1) {
+ digitStrings = null;
+ codePointZero = _codePointZero;
+ } else {
+ digitStrings = symbols.getDigitStrings(); // makes a copy
+ codePointZero = -1;
+ }
+ }
+
+ @Override
+ public int target(FormatQuantity input, NumberStringBuilder string, int startIndex) {
+ int length = 0;
+
+ if (input.isInfinite()) {
+ length += string.insert(startIndex, infinityString, NumberFormat.Field.INTEGER);
+
+ } else if (input.isNaN()) {
+ length += string.insert(startIndex, nanString, NumberFormat.Field.INTEGER);
+
+ } else {
+ // Add the integer digits
+ length += addIntegerDigits(input, string, startIndex);
+
+ // Add the decimal point
+ if (input.getLowerDisplayMagnitude() < 0 || alwaysShowDecimal) {
+ length += string.insert(startIndex + length, decimalSeparator, NumberFormat.Field.DECIMAL_SEPARATOR);
+ }
+
+ // Add the fraction digits
+ length += addFractionDigits(input, string, startIndex + length);
+ }
+
+ return length;
+ }
+
+ private int addIntegerDigits(FormatQuantity input, NumberStringBuilder string, int startIndex) {
+ int length = 0;
+ int integerCount = input.getUpperDisplayMagnitude() + 1;
+ for (int i = 0; i < integerCount; i++) {
+ // Add grouping separator
+ if (groupingSize > 0 && i == groupingSize && integerCount - i >= minimumGroupingDigits) {
+ length += string.insert(startIndex, groupingSeparator, NumberFormat.Field.GROUPING_SEPARATOR);
+ } else if (secondaryGroupingSize > 0
+ && i > groupingSize
+ && (i - groupingSize) % secondaryGroupingSize == 0) {
+ length += string.insert(startIndex, groupingSeparator, NumberFormat.Field.GROUPING_SEPARATOR);
+ }
+
+ // Get and append the next digit value
+ byte nextDigit = input.getDigit(i);
+ length += addDigit(nextDigit, string, startIndex, NumberFormat.Field.INTEGER);
+ }
+
+ return length;
+ }
+
+ private int addFractionDigits(FormatQuantity input, NumberStringBuilder string, int index) {
+ int length = 0;
+ int fractionCount = -input.getLowerDisplayMagnitude();
+ for (int i = 0; i < fractionCount; i++) {
+ // Get and append the next digit value
+ byte nextDigit = input.getDigit(-i - 1);
+ length += addDigit(nextDigit, string, index + length, NumberFormat.Field.FRACTION);
+ }
+ return length;
+ }
+
+ private int addDigit(byte digit, NumberStringBuilder outputString, int index, Field field) {
+ if (codePointZero != -1) {
+ return outputString.insertCodePoint(index, codePointZero + digit, field);
+ } else {
+ return outputString.insert(index, digitStrings[digit], field);
+ }
+ }
+
+ @Override
+ public void export(Properties properties) {
+ properties.setDecimalSeparatorAlwaysShown(alwaysShowDecimal);
+ properties.setGroupingSize(groupingSize);
+ properties.setSecondaryGroupingSize(secondaryGroupingSize);
+ properties.setMinimumGroupingDigits(minimumGroupingDigits);
+ }
+}
Property changes on: icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain;charset=utf-8
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property

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