From 8cf6752ecbfad6bc1c7e61a6caabdb83e7744763 Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Fri, 28 Jul 2017 05:55:06 +0000 Subject: [PATCH] ICU-13177 Assorted minor internal changes. X-SVN-Rev: 40294 --- .../icu/impl/number/AffixPatternUtils.java | 54 +++++++++---------- .../src/com/ibm/icu/impl/number/Modifier.java | 7 --- .../ibm/icu/impl/number/ModifierHolder.java | 20 +++---- .../icu/impl/number/NumberStringBuilder.java | 39 ++++++++++++++ .../impl/number/formatters/PaddingFormat.java | 16 +++--- .../modifiers/ConstantAffixModifier.java | 12 +---- .../modifiers/ConstantMultiFieldModifier.java | 16 ++---- .../impl/number/modifiers/SimpleModifier.java | 6 --- 8 files changed, 85 insertions(+), 85 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java index f1357836ba5..f1835d15f04 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java @@ -3,7 +3,7 @@ package com.ibm.icu.impl.number; import com.ibm.icu.text.DecimalFormatSymbols; -import com.ibm.icu.text.NumberFormat.Field; +import com.ibm.icu.text.NumberFormat; /** * Performs manipulations on affix patterns: the prefix and suffix strings associated with a decimal @@ -251,37 +251,38 @@ public class AffixPatternUtils { while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern); int typeOrCp = getTypeOrCp(tag); + NumberFormat.Field field = (typeOrCp < 0) ? getFieldForType(typeOrCp) : null; switch (typeOrCp) { case TYPE_MINUS_SIGN: - output.append(minusSign, Field.SIGN); + output.append(minusSign, field); break; case TYPE_PLUS_SIGN: - output.append(symbols.getPlusSignString(), Field.SIGN); + output.append(symbols.getPlusSignString(), field); break; case TYPE_PERCENT: - output.append(symbols.getPercentString(), Field.PERCENT); + output.append(symbols.getPercentString(), field); break; case TYPE_PERMILLE: - output.append(symbols.getPerMillString(), Field.PERMILLE); + output.append(symbols.getPerMillString(), field); break; case TYPE_CURRENCY_SINGLE: - output.append(currency1, Field.CURRENCY); + output.append(currency1, field); break; case TYPE_CURRENCY_DOUBLE: - output.append(currency2, Field.CURRENCY); + output.append(currency2, field); break; case TYPE_CURRENCY_TRIPLE: - output.append(currency3, Field.CURRENCY); + output.append(currency3, field); break; case TYPE_CURRENCY_QUAD: - output.appendCodePoint('\uFFFD', Field.CURRENCY); + output.appendCodePoint('\uFFFD', field); break; case TYPE_CURRENCY_QUINT: // TODO: Add support for narrow currency symbols here. - output.appendCodePoint('\uFFFD', Field.CURRENCY); + output.appendCodePoint('\uFFFD', field); break; case TYPE_CURRENCY_OVERFLOW: - output.appendCodePoint('\uFFFD', Field.CURRENCY); + output.appendCodePoint('\uFFFD', field); break; default: output.appendCodePoint(typeOrCp, null); @@ -290,28 +291,28 @@ public class AffixPatternUtils { } } - private static final Field getFieldForType(int type) { + public static final NumberFormat.Field getFieldForType(int type) { switch (type) { case TYPE_MINUS_SIGN: - return Field.SIGN; + return NumberFormat.Field.SIGN; case TYPE_PLUS_SIGN: - return Field.SIGN; + return NumberFormat.Field.SIGN; case TYPE_PERCENT: - return Field.PERCENT; + return NumberFormat.Field.PERCENT; case TYPE_PERMILLE: - return Field.PERMILLE; + return NumberFormat.Field.PERMILLE; case TYPE_CURRENCY_SINGLE: - return Field.CURRENCY; + return NumberFormat.Field.CURRENCY; case TYPE_CURRENCY_DOUBLE: - return Field.CURRENCY; + return NumberFormat.Field.CURRENCY; case TYPE_CURRENCY_TRIPLE: - return Field.CURRENCY; + return NumberFormat.Field.CURRENCY; case TYPE_CURRENCY_QUAD: - return Field.CURRENCY; + return NumberFormat.Field.CURRENCY; case TYPE_CURRENCY_QUINT: - return Field.CURRENCY; + return NumberFormat.Field.CURRENCY; case TYPE_CURRENCY_OVERFLOW: - return Field.CURRENCY; + return NumberFormat.Field.CURRENCY; default: throw new AssertionError(); } @@ -335,7 +336,7 @@ public class AffixPatternUtils { int typeOrCp = getTypeOrCp(tag); if (typeOrCp == TYPE_CURRENCY_OVERFLOW) { // Don't go to the provider for this special case - local.appendCodePoint(0xFFFD, Field.CURRENCY); + local.appendCodePoint(0xFFFD, NumberFormat.Field.CURRENCY); } else if (typeOrCp < 0) { local.append(provider.getSymbol(typeOrCp), getFieldForType(typeOrCp)); } else { @@ -377,12 +378,7 @@ public class AffixPatternUtils { while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern); int typeOrCp = getTypeOrCp(tag); - if (typeOrCp == AffixPatternUtils.TYPE_CURRENCY_SINGLE - || typeOrCp == AffixPatternUtils.TYPE_CURRENCY_DOUBLE - || typeOrCp == AffixPatternUtils.TYPE_CURRENCY_TRIPLE - || typeOrCp == AffixPatternUtils.TYPE_CURRENCY_QUAD - || typeOrCp == AffixPatternUtils.TYPE_CURRENCY_QUINT - || typeOrCp == AffixPatternUtils.TYPE_CURRENCY_OVERFLOW) { + if (typeOrCp < 0 && getFieldForType(typeOrCp) == NumberFormat.Field.CURRENCY) { return true; } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java index 00739fd5743..8cb1ced988a 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java @@ -33,13 +33,6 @@ public interface Modifier { */ public int apply(NumberStringBuilder output, int leftIndex, int rightIndex); - /** - * The number of characters that {@link #apply} would add to the string builder. - * - * @return The number of characters (UTF-16 code units) that would be added to a string builder. - */ - public int length(); - /** * Whether this modifier is strong. If a modifier is strong, it should always be applied * immediately and not allowed to bubble up. With regard to padding, strong modifiers are diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierHolder.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierHolder.java index 483d6fd6792..a35647c3bb5 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierHolder.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierHolder.java @@ -17,6 +17,12 @@ public class ModifierHolder { // private Modifier mod4 = null; // private Modifier mod5 = null; + public ModifierHolder createCopy() { + ModifierHolder copy = new ModifierHolder(); + copy.mods.addAll(mods); + return copy; + } + public ModifierHolder clear() { // mod1 = null; // mod2 = null; @@ -89,18 +95,4 @@ public class ModifierHolder { } return addedLength; } - - public int totalLength() { - int length = 0; - // if (mod1 != null) length += mod1.length(); - // if (mod2 != null) length += mod2.length(); - // if (mod3 != null) length += mod3.length(); - // if (mod4 != null) length += mod4.length(); - // if (mod5 != null) length += mod5.length(); - for (Modifier mod : mods) { - if (mod == null) continue; - length += mod.length(); - } - return length; - } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/NumberStringBuilder.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/NumberStringBuilder.java index 7ea35f2b568..ad4a52f6be6 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/NumberStringBuilder.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/NumberStringBuilder.java @@ -12,7 +12,21 @@ import java.util.Map; import com.ibm.icu.text.NumberFormat; import com.ibm.icu.text.NumberFormat.Field; +/** + * A StringBuilder optimized for number formatting. It implements the following key features beyond + * a normal JDK StringBuilder: + * + *
    + *
  1. Efficient prepend as well as append. + *
  2. Keeps tracks of Fields in an efficient manner. + *
  3. String operations are fast-pathed to code point operations when possible. + *
+ */ public class NumberStringBuilder implements CharSequence { + + /** A constant, empty NumberStringBuilder. Do NOT call mutative operations on this. */ + public static final NumberStringBuilder EMPTY = new NumberStringBuilder(); + private char[] chars; private Field[] fields; private int zero; @@ -31,6 +45,10 @@ public class NumberStringBuilder implements CharSequence { public NumberStringBuilder(NumberStringBuilder source) { this(source.chars.length); + copyFrom(source); + } + + public void copyFrom(NumberStringBuilder source) { zero = source.zero; length = source.length; System.arraycopy(source.chars, zero, chars, zero, length); @@ -42,6 +60,10 @@ public class NumberStringBuilder implements CharSequence { return length; } + public int codePointCount() { + return Character.codePointCount(this, 0, length()); + } + @Override public char charAt(int index) { if (index < 0 || index > length) { @@ -50,6 +72,13 @@ public class NumberStringBuilder implements CharSequence { return chars[zero + index]; } + public Field fieldAt(int index) { + if (index < 0 || index > length) { + throw new IndexOutOfBoundsException(); + } + return fields[zero + index]; + } + /** * Appends the specified codePoint to the end of the string. * @@ -325,6 +354,16 @@ public class NumberStringBuilder implements CharSequence { return true; } + @Override + public int hashCode() { + throw new UnsupportedOperationException("Don't call #hashCode() or #equals() on a mutable."); + } + + @Override + public boolean equals(Object other) { + throw new UnsupportedOperationException("Don't call #hashCode() or #equals() on a mutable."); + } + /** * Populates the given {@link FieldPosition} based on this string builder. * diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PaddingFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PaddingFormat.java index 5aa3c48c63f..77eb6dc1c62 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PaddingFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PaddingFormat.java @@ -112,9 +112,7 @@ public class PaddingFormat implements AfterFormat { public static AfterFormat getInstance(IProperties properties) { return new PaddingFormat( - properties.getFormatWidth(), - properties.getPadString(), - properties.getPadPosition()); + properties.getFormatWidth(), properties.getPadString(), properties.getPadPosition()); } // Properties @@ -122,19 +120,21 @@ public class PaddingFormat implements AfterFormat { private final String paddingString; private final PadPosition paddingLocation; - private PaddingFormat( - int paddingWidth, String paddingString, PadPosition paddingLocation) { + private PaddingFormat(int paddingWidth, String paddingString, PadPosition paddingLocation) { this.paddingWidth = paddingWidth > 0 ? paddingWidth : 10; // TODO: Is this a sensible default? this.paddingString = paddingString != null ? paddingString : FALLBACK_PADDING_STRING; - this.paddingLocation = - paddingLocation != null ? paddingLocation : PadPosition.BEFORE_PREFIX; + this.paddingLocation = paddingLocation != null ? paddingLocation : PadPosition.BEFORE_PREFIX; } @Override public int after(ModifierHolder mods, NumberStringBuilder string, int leftIndex, int rightIndex) { // TODO: Count code points instead of code units? - int requiredPadding = paddingWidth - (rightIndex - leftIndex) - mods.totalLength(); + // TODO: Make this more efficient (less copying) + NumberStringBuilder copy1 = new NumberStringBuilder(string); + ModifierHolder copy2 = mods.createCopy(); + copy2.applyAll(copy1, leftIndex, rightIndex); + int requiredPadding = paddingWidth - copy1.length(); if (requiredPadding <= 0) { // Skip padding, but still apply modifiers to be consistent diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantAffixModifier.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantAffixModifier.java index 2eea973956e..ba46aa9d0cb 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantAffixModifier.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantAffixModifier.java @@ -40,9 +40,7 @@ public class ConstantAffixModifier extends Modifier.BaseModifier implements Affi this.strong = strong; } - /** - * Constructs a new instance with an empty prefix, suffix, and field. - */ + /** Constructs a new instance with an empty prefix, suffix, and field. */ public ConstantAffixModifier() { prefix = ""; suffix = ""; @@ -58,11 +56,6 @@ public class ConstantAffixModifier extends Modifier.BaseModifier implements Affi return length; } - @Override - public int length() { - return prefix.length() + suffix.length(); - } - @Override public boolean isStrong() { return strong; @@ -94,8 +87,7 @@ public class ConstantAffixModifier extends Modifier.BaseModifier implements Affi @Override public String toString() { - return String.format( - "", length(), prefix, suffix); + return String.format("", prefix, suffix); } @Override diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantMultiFieldModifier.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantMultiFieldModifier.java index e7ed0a61234..499f6d7ee04 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantMultiFieldModifier.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/ConstantMultiFieldModifier.java @@ -18,10 +18,10 @@ public class ConstantMultiFieldModifier extends Modifier.BaseModifier implements // TODO: Avoid making a new instance by default if prefix and suffix are empty public static final ConstantMultiFieldModifier EMPTY = new ConstantMultiFieldModifier(); - private final char[] prefixChars; - private final char[] suffixChars; - private final Field[] prefixFields; - private final Field[] suffixFields; + protected final char[] prefixChars; + protected final char[] suffixChars; + protected final Field[] prefixFields; + protected final Field[] suffixFields; private final String prefix; private final String suffix; private final boolean strong; @@ -55,11 +55,6 @@ public class ConstantMultiFieldModifier extends Modifier.BaseModifier implements return length; } - @Override - public int length() { - return prefixChars.length + suffixChars.length; - } - @Override public boolean isStrong() { return strong; @@ -82,8 +77,7 @@ public class ConstantMultiFieldModifier extends Modifier.BaseModifier implements @Override public String toString() { - return String.format( - "", length(), prefix, suffix); + return String.format("", prefix, suffix); } @Override diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/SimpleModifier.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/SimpleModifier.java index 23a15f44aac..63f1cc1cd1d 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/SimpleModifier.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/modifiers/SimpleModifier.java @@ -29,12 +29,6 @@ public class SimpleModifier extends Modifier.BaseModifier { return formatAsPrefixSuffix(compiledPattern, output, leftIndex, rightIndex, field); } - @Override - public int length() { - // TODO: Make a separate method for computing the length only? - return formatAsPrefixSuffix(compiledPattern, null, -1, -1, field); - } - @Override public boolean isStrong() { return strong; -- 2.50.1