* @param patternString The original string whose width will be estimated.
* @return The length of the unescaped string.
*/
- public static int unescapedLength(CharSequence patternString) {
+ public static int estimateLength(CharSequence patternString) {
if (patternString == null) return 0;
int state = STATE_BASE;
int offset = 0;
local.appendCodePoint(typeOrCp, null);
}
}
- return output.insert(position, local);
+ if (output != null) {
+ output.insert(position, local);
+ }
+ return local.length();
}
/**
import com.ibm.icu.impl.number.modifiers.SimpleModifier;
/**
- * A Modifier is an immutable object that can be passed through the formatting pipeline until it is
- * finally applied to the string builder. A Modifier usually contains a prefix and a suffix that are
- * applied, but it could contain something else, like a {@link com.ibm.icu.text.SimpleFormatter}
- * pattern.
+ * A Modifier is an immutable object that can be passed through the formatting pipeline until it is finally applied to
+ * the string builder. A Modifier usually contains a prefix and a suffix that are applied, but it could contain
+ * something else, like a {@link com.ibm.icu.text.SimpleFormatter} pattern.
*
* @see PositiveNegativeAffixModifier
* @see ConstantAffixModifier
*/
public interface Modifier {
- /**
- * Apply this Modifier to the string builder.
- *
- * @param output The string builder to which to apply this modifier.
- * @param leftIndex The left index of the string within the builder. Equal to 0 when only one
- * number is being formatted.
- * @param rightIndex The right index of the string within the string builder. Equal to length-1
- * when only one number is being formatted.
- * @return The number of characters (UTF-16 code units) that were added to the string builder.
- */
- public int apply(NumberStringBuilder output, int leftIndex, int rightIndex);
-
- /**
- * 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
- * considered to be on the inside of the prefix and suffix.
- *
- * @return Whether the modifier is strong.
- */
- public boolean isStrong();
-
- /**
- * Gets the prefix string associated with this modifier, defined as the string that will be
- * inserted at leftIndex when {@link #apply} is called.
- *
- * <p>TODO: Change this to appendPrefixTo(), or remove it entirely and do something different at
- * the call sites.
- *
- * @return The prefix string. Will not be null.
- */
- public String getPrefix();
-
- /**
- * Gets the prefix string associated with this modifier, defined as the string that will be
- * inserted at rightIndex when {@link #apply} is called.
- *
- * <p>TODO: Change this to appendPrefixTo(), or remove it entirely and do something different at
- * the call sites.
- *
- * @return The suffix string. Will not be null.
- */
- public String getSuffix();
+ /**
+ * Apply this Modifier to the string builder.
+ *
+ * @param output
+ * The string builder to which to apply this modifier.
+ * @param leftIndex
+ * The left index of the string within the builder. Equal to 0 when only one number is being formatted.
+ * @param rightIndex
+ * The right index of the string within the string builder. Equal to length-1 when only one number is
+ * being formatted.
+ * @return The number of characters (UTF-16 code units) that were added to the string builder.
+ */
+ public int apply(NumberStringBuilder output, int leftIndex, int rightIndex);
- /**
- * An interface for a modifier that contains both a positive and a negative form. Note that a
- * class implementing {@link PositiveNegativeModifier} is not necessarily a {@link Modifier}
- * itself. Rather, it returns a {@link Modifier} when {@link #getModifier} is called.
- */
- public static interface PositiveNegativeModifier {
/**
- * Converts this {@link PositiveNegativeModifier} to a {@link Modifier} given the negative sign.
+ * Gets the length of the prefix. This information can be used in combination with {@link #apply} to extract the
+ * prefix and suffix strings.
*
- * @param isNegative true if the negative form of this modifier should be used; false if the
- * positive form should be used.
- * @return A Modifier corresponding to the negative sign.
+ * @return The number of characters (UTF-16 code units) in the prefix.
*/
- public Modifier getModifier(boolean isNegative);
- }
+ public int getPrefixLength();
- /**
- * An interface for a modifier that contains both a positive and a negative form for all six
- * standard plurals. Note that a class implementing {@link PositiveNegativePluralModifier} is not
- * necessarily a {@link Modifier} itself. Rather, it returns a {@link Modifier} when {@link
- * #getModifier} is called.
- */
- public static interface PositiveNegativePluralModifier {
/**
- * Converts this {@link PositiveNegativePluralModifier} to a {@link Modifier} given the negative
- * sign and the standard plural.
+ * 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 considered to be on the inside of the prefix and
+ * suffix.
*
- * @param plural The StandardPlural to use.
- * @param isNegative true if the negative form of this modifier should be used; false if the
- * positive form should be used.
- * @return A Modifier corresponding to the negative sign.
+ * @return Whether the modifier is strong.
+ */
+ public boolean isStrong();
+
+ /**
+ * An interface for a modifier that contains both a positive and a negative form. Note that a class implementing
+ * {@link PositiveNegativeModifier} is not necessarily a {@link Modifier} itself. Rather, it returns a
+ * {@link Modifier} when {@link #getModifier} is called.
+ */
+ public static interface PositiveNegativeModifier {
+ /**
+ * Converts this {@link PositiveNegativeModifier} to a {@link Modifier} given the negative sign.
+ *
+ * @param isNegative
+ * true if the negative form of this modifier should be used; false if the positive form should be
+ * used.
+ * @return A Modifier corresponding to the negative sign.
+ */
+ public Modifier getModifier(boolean isNegative);
+ }
+
+ /**
+ * An interface for a modifier that contains both a positive and a negative form for all six standard plurals. Note
+ * that a class implementing {@link PositiveNegativePluralModifier} is not necessarily a {@link Modifier} itself.
+ * Rather, it returns a {@link Modifier} when {@link #getModifier} is called.
*/
- public Modifier getModifier(StandardPlural plural, boolean isNegative);
- }
+ public static interface PositiveNegativePluralModifier {
+ /**
+ * Converts this {@link PositiveNegativePluralModifier} to a {@link Modifier} given the negative sign and the
+ * standard plural.
+ *
+ * @param plural
+ * The StandardPlural to use.
+ * @param isNegative
+ * true if the negative form of this modifier should be used; false if the positive form should be
+ * used.
+ * @return A Modifier corresponding to the negative sign.
+ */
+ public Modifier getModifier(StandardPlural plural, boolean isNegative);
+ }
- /**
- * An interface for a modifier that is represented internally by a prefix string and a suffix
- * string.
- */
- public static interface AffixModifier extends Modifier {}
+ /**
+ * An interface for a modifier that is represented internally by a prefix string and a suffix string.
+ */
+ public static interface AffixModifier extends Modifier {
+ }
- /**
- * A starter implementation with defaults for some of the basic methods.
- *
- * <p>Implements {@link PositiveNegativeModifier} only so that instances of this class can be used
- * when a {@link PositiveNegativeModifier} is required.
- */
- public abstract static class BaseModifier implements Modifier, PositiveNegativeModifier {
+ /**
+ * A starter implementation with defaults for some of the basic methods.
+ *
+ * <p>
+ * Implements {@link PositiveNegativeModifier} only so that instances of this class can be used when a
+ * {@link PositiveNegativeModifier} is required.
+ */
+ public abstract static class BaseModifier implements Modifier, PositiveNegativeModifier {
- @Override
- public Modifier getModifier(boolean isNegative) {
- return this;
+ @Override
+ public Modifier getModifier(boolean isNegative) {
+ return this;
+ }
}
- }
}
// The width of the positive prefix and suffix templates are included in the padding
int paddingWidth =
positive.paddingWidth
- + AffixPatternUtils.unescapedLength(posPrefix)
- + AffixPatternUtils.unescapedLength(posSuffix);
+ + AffixPatternUtils.estimateLength(posPrefix)
+ + AffixPatternUtils.estimateLength(posSuffix);
properties.setFormatWidth(paddingWidth);
String rawPaddingString = ppr.getString(AffixPatternProvider.Flags.PADDING);
if (rawPaddingString.length() == 1) {
/** The canonical implementation of {@link Modifier}, containing a prefix and suffix string. */
public class ConstantAffixModifier extends Modifier.BaseModifier implements AffixModifier {
- // TODO: Avoid making a new instance by default if prefix and suffix are empty
- public static final AffixModifier EMPTY = new ConstantAffixModifier();
+ // TODO: Avoid making a new instance by default if prefix and suffix are empty
+ public static final AffixModifier EMPTY = new ConstantAffixModifier();
- private final String prefix;
- private final String suffix;
- private final Field field;
- private final boolean strong;
+ private final String prefix;
+ private final String suffix;
+ private final Field field;
+ private final boolean strong;
- /**
- * Constructs an instance with the given strings.
- *
- * <p>The arguments need to be Strings, not CharSequences, because Strings are immutable but
- * CharSequences are not.
- *
- * @param prefix The prefix string.
- * @param suffix The suffix string.
- * @param field The field type to be associated with this modifier. Can be null.
- * @param strong Whether this modifier should be strongly applied.
- * @see Field
- */
- public ConstantAffixModifier(String prefix, String suffix, Field field, boolean strong) {
- // Use an empty string instead of null if we are given null
- // TODO: Consider returning a null modifier if both prefix and suffix are empty.
- this.prefix = (prefix == null ? "" : prefix);
- this.suffix = (suffix == null ? "" : suffix);
- this.field = field;
- this.strong = strong;
- }
-
- /** Constructs a new instance with an empty prefix, suffix, and field. */
- public ConstantAffixModifier() {
- prefix = "";
- suffix = "";
- field = null;
- strong = false;
- }
-
- @Override
- public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
- // Insert the suffix first since inserting the prefix will change the rightIndex
- int length = output.insert(rightIndex, suffix, field);
- length += output.insert(leftIndex, prefix, field);
- return length;
- }
+ /**
+ * Constructs an instance with the given strings.
+ *
+ * <p>
+ * The arguments need to be Strings, not CharSequences, because Strings are immutable but CharSequences are not.
+ *
+ * @param prefix
+ * The prefix string.
+ * @param suffix
+ * The suffix string.
+ * @param field
+ * The field type to be associated with this modifier. Can be null.
+ * @param strong
+ * Whether this modifier should be strongly applied.
+ * @see Field
+ */
+ public ConstantAffixModifier(String prefix, String suffix, Field field, boolean strong) {
+ // Use an empty string instead of null if we are given null
+ // TODO: Consider returning a null modifier if both prefix and suffix are empty.
+ this.prefix = (prefix == null ? "" : prefix);
+ this.suffix = (suffix == null ? "" : suffix);
+ this.field = field;
+ this.strong = strong;
+ }
- @Override
- public boolean isStrong() {
- return strong;
- }
+ /** Constructs a new instance with an empty prefix, suffix, and field. */
+ public ConstantAffixModifier() {
+ prefix = "";
+ suffix = "";
+ field = null;
+ strong = false;
+ }
- @Override
- public String getPrefix() {
- return prefix;
- }
+ @Override
+ public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
+ // Insert the suffix first since inserting the prefix will change the rightIndex
+ int length = output.insert(rightIndex, suffix, field);
+ length += output.insert(leftIndex, prefix, field);
+ return length;
+ }
- @Override
- public String getSuffix() {
- return suffix;
- }
+ @Override
+ public int getPrefixLength() {
+ return prefix.length();
+ }
- public boolean contentEquals(CharSequence _prefix, CharSequence _suffix) {
- if (_prefix == null && !prefix.isEmpty()) return false;
- if (_suffix == null && !suffix.isEmpty()) return false;
- if (_prefix != null && prefix.length() != _prefix.length()) return false;
- if (_suffix != null && suffix.length() != _suffix.length()) return false;
- for (int i = 0; i < prefix.length(); i++) {
- if (prefix.charAt(i) != _prefix.charAt(i)) return false;
+ @Override
+ public boolean isStrong() {
+ return strong;
}
- for (int i = 0; i < suffix.length(); i++) {
- if (suffix.charAt(i) != _suffix.charAt(i)) return false;
+
+ public boolean contentEquals(CharSequence _prefix, CharSequence _suffix) {
+ if (_prefix == null && !prefix.isEmpty())
+ return false;
+ if (_suffix == null && !suffix.isEmpty())
+ return false;
+ if (_prefix != null && prefix.length() != _prefix.length())
+ return false;
+ if (_suffix != null && suffix.length() != _suffix.length())
+ return false;
+ for (int i = 0; i < prefix.length(); i++) {
+ if (prefix.charAt(i) != _prefix.charAt(i))
+ return false;
+ }
+ for (int i = 0; i < suffix.length(); i++) {
+ if (suffix.charAt(i) != _suffix.charAt(i))
+ return false;
+ }
+ return true;
}
- return true;
- }
- @Override
- public String toString() {
- return String.format("<ConstantAffixModifier prefix:'%s' suffix:'%s'>", prefix, suffix);
- }
+ @Override
+ public String toString() {
+ return String.format("<ConstantAffixModifier prefix:'%s' suffix:'%s'>", prefix, suffix);
+ }
}
import com.ibm.icu.text.NumberFormat.Field;
/**
- * An implementation of {@link Modifier} that allows for multiple types of fields in the same
- * modifier. Constructed based on the contents of two {@link NumberStringBuilder} instances (one for
- * the prefix, one for the suffix).
+ * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed
+ * based on the contents of two {@link NumberStringBuilder} instances (one for the prefix, one for the suffix).
*/
public class ConstantMultiFieldModifier extends Modifier.BaseModifier implements AffixModifier {
- // TODO: Avoid making a new instance by default if prefix and suffix are empty
- public static final ConstantMultiFieldModifier EMPTY = new ConstantMultiFieldModifier();
+ // TODO: Avoid making a new instance by default if prefix and suffix are empty
+ public static final ConstantMultiFieldModifier EMPTY = new ConstantMultiFieldModifier();
- 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;
+ protected final char[] prefixChars;
+ protected final char[] suffixChars;
+ protected final Field[] prefixFields;
+ protected final Field[] suffixFields;
+ private final boolean strong;
- public ConstantMultiFieldModifier(
- NumberStringBuilder prefix, NumberStringBuilder suffix, boolean strong) {
- prefixChars = prefix.toCharArray();
- suffixChars = suffix.toCharArray();
- prefixFields = prefix.toFieldArray();
- suffixFields = suffix.toFieldArray();
- this.prefix = new String(prefixChars);
- this.suffix = new String(suffixChars);
- this.strong = strong;
- }
+ public ConstantMultiFieldModifier(NumberStringBuilder prefix, NumberStringBuilder suffix, boolean strong) {
+ prefixChars = prefix.toCharArray();
+ suffixChars = suffix.toCharArray();
+ prefixFields = prefix.toFieldArray();
+ suffixFields = suffix.toFieldArray();
+ this.strong = strong;
+ }
- private ConstantMultiFieldModifier() {
- prefixChars = new char[0];
- suffixChars = new char[0];
- prefixFields = new Field[0];
- suffixFields = new Field[0];
- prefix = "";
- suffix = "";
- strong = false;
- }
+ private ConstantMultiFieldModifier() {
+ prefixChars = new char[0];
+ suffixChars = new char[0];
+ prefixFields = new Field[0];
+ suffixFields = new Field[0];
+ strong = false;
+ }
- @Override
- public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
- // Insert the suffix first since inserting the prefix will change the rightIndex
- int length = output.insert(rightIndex, suffixChars, suffixFields);
- length += output.insert(leftIndex, prefixChars, prefixFields);
- return length;
- }
+ @Override
+ public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
+ // Insert the suffix first since inserting the prefix will change the rightIndex
+ int length = output.insert(rightIndex, suffixChars, suffixFields);
+ length += output.insert(leftIndex, prefixChars, prefixFields);
+ return length;
+ }
- @Override
- public boolean isStrong() {
- return strong;
- }
+ @Override
+ public int getPrefixLength() {
+ return prefixChars.length;
+ }
- @Override
- public String getPrefix() {
- return prefix;
- }
+ @Override
+ public boolean isStrong() {
+ return strong;
+ }
- @Override
- public String getSuffix() {
- return suffix;
- }
+ public boolean contentEquals(NumberStringBuilder prefix, NumberStringBuilder suffix) {
+ return prefix.contentEquals(prefixChars, prefixFields) && suffix.contentEquals(suffixChars, suffixFields);
+ }
- public boolean contentEquals(NumberStringBuilder prefix, NumberStringBuilder suffix) {
- return prefix.contentEquals(prefixChars, prefixFields)
- && suffix.contentEquals(suffixChars, suffixFields);
- }
-
- @Override
- public String toString() {
- return String.format("<ConstantMultiFieldModifier prefix:'%s' suffix:'%s'>", prefix, suffix);
- }
+ @Override
+ public String toString() {
+ NumberStringBuilder temp = new NumberStringBuilder();
+ apply(temp, 0, 0);
+ int prefixLength = getPrefixLength();
+ return String.format("<ConstantMultiFieldModifier prefix:'%s' suffix:'%s'>", temp.subSequence(0, prefixLength),
+ temp.subSequence(prefixLength, temp.length()));
+ }
}
import com.ibm.icu.text.NumberFormat.Field;
/**
- * The second primary implementation of {@link Modifier}, this one consuming a {@link
- * com.ibm.icu.text.SimpleFormatter} pattern.
+ * The second primary implementation of {@link Modifier}, this one consuming a {@link com.ibm.icu.text.SimpleFormatter}
+ * pattern.
*/
public class SimpleModifier extends Modifier.BaseModifier {
- private final String compiledPattern;
- private final Field field;
- private final boolean strong;
+ private final String compiledPattern;
+ private final Field field;
+ private final boolean strong;
- private final int prefixLength;
- private final int suffixOffset;
- private final int suffixLength;
+ private final int prefixLength;
+ private final int suffixOffset;
+ private final int suffixLength;
- private static final int ARG_NUM_LIMIT = 0x100;
+ private static final int ARG_NUM_LIMIT = 0x100;
- /** Creates a modifier that uses the SimpleFormatter string formats. */
- public SimpleModifier(String compiledPattern, Field field, boolean strong) {
- this.compiledPattern = (compiledPattern == null) ? "\u0001\u0000" : compiledPattern;
- this.field = field;
- this.strong = strong;
+ /** Creates a modifier that uses the SimpleFormatter string formats. */
+ public SimpleModifier(String compiledPattern, Field field, boolean strong) {
+ this.compiledPattern = (compiledPattern == null) ? "\u0001\u0000" : compiledPattern;
+ this.field = field;
+ this.strong = strong;
- assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
- if (compiledPattern.charAt(1) != '\u0000') {
- prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
- suffixOffset = 3 + prefixLength;
- } else {
- prefixLength = 0;
- suffixOffset = 2;
+ assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
+ if (compiledPattern.charAt(1) != '\u0000') {
+ prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
+ suffixOffset = 3 + prefixLength;
+ } else {
+ prefixLength = 0;
+ suffixOffset = 2;
+ }
+ if (3 + prefixLength < compiledPattern.length()) {
+ suffixLength = compiledPattern.charAt(suffixOffset) - ARG_NUM_LIMIT;
+ } else {
+ suffixLength = 0;
+ }
}
- if (3 + prefixLength < compiledPattern.length()) {
- suffixLength = compiledPattern.charAt(suffixOffset) - ARG_NUM_LIMIT;
- } else {
- suffixLength = 0;
- }
- }
-
- @Override
- public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
- return formatAsPrefixSuffix(output, leftIndex, rightIndex, field);
- }
- @Override
- public boolean isStrong() {
- return strong;
- }
-
- @Override
- public String getPrefix() {
- if (prefixLength == 0) {
- return "";
+ @Override
+ public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
+ return formatAsPrefixSuffix(output, leftIndex, rightIndex, field);
}
- return compiledPattern.substring(2, 2 + prefixLength);
- }
- @Override
- public String getSuffix() {
- if (suffixLength == 0) {
- return "";
+ @Override
+ public int getPrefixLength() {
+ return prefixLength;
}
- return compiledPattern.substring(1 + suffixOffset, 1 + suffixOffset + suffixLength);
- }
- /**
- * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is
- * because DoubleSidedStringBuilder is an internal class and SimpleFormatterImpl feels like it
- * should not depend on it.
- *
- * <p>Formats a value that is already stored inside the StringBuilder <code>result</code> between
- * the indices <code>startIndex</code> and <code>endIndex</code> by inserting characters before
- * the start index and after the end index.
- *
- * <p>This is well-defined only for patterns with exactly one argument.
- *
- * @param result The StringBuilder containing the value argument.
- * @param startIndex The left index of the value within the string builder.
- * @param endIndex The right index of the value within the string builder.
- * @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
- */
- public int formatAsPrefixSuffix(
- NumberStringBuilder result, int startIndex, int endIndex, Field field) {
- assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
- if (prefixLength > 0) {
- result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
+ @Override
+ public boolean isStrong() {
+ return strong;
}
- if (suffixLength > 0) {
- result.insert(
- endIndex + prefixLength,
- compiledPattern,
- 1 + suffixOffset,
- 1 + suffixOffset + suffixLength,
- field);
+
+ /**
+ * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because
+ * DoubleSidedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
+ *
+ * <p>
+ * Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices
+ * <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start index and after the
+ * end index.
+ *
+ * <p>
+ * This is well-defined only for patterns with exactly one argument.
+ *
+ * @param result
+ * The StringBuilder containing the value argument.
+ * @param startIndex
+ * The left index of the value within the string builder.
+ * @param endIndex
+ * The right index of the value within the string builder.
+ * @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
+ */
+ public int formatAsPrefixSuffix(NumberStringBuilder result, int startIndex, int endIndex, Field field) {
+ assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
+ if (prefixLength > 0) {
+ result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
+ }
+ if (suffixLength > 0) {
+ result.insert(endIndex + prefixLength, compiledPattern, 1 + suffixOffset, 1 + suffixOffset + suffixLength,
+ field);
+ }
+ return prefixLength + suffixLength;
}
- return prefixLength + suffixLength;
- }
- /** TODO: Move this to a test file somewhere, once we figure out what to do with the method. */
- public static void testFormatAsPrefixSuffix() {
- String[] patterns = {"{0}", "X{0}Y", "XX{0}YYY", "{0}YY", "XXXX{0}"};
- Object[][] outputs = {{"", 0, 0}, {"abcde", 0, 0}, {"abcde", 2, 2}, {"abcde", 1, 3}};
- String[][] expecteds = {
- {"", "XY", "XXYYY", "YY", "XXXX"},
- {"abcde", "XYabcde", "XXYYYabcde", "YYabcde", "XXXXabcde"},
- {"abcde", "abXYcde", "abXXYYYcde", "abYYcde", "abXXXXcde"},
- {"abcde", "aXbcYde", "aXXbcYYYde", "abcYYde", "aXXXXbcde"}
- };
- for (int i = 0; i < patterns.length; i++) {
- for (int j = 0; j < outputs.length; j++) {
- String pattern = patterns[i];
- String compiledPattern =
- SimpleFormatterImpl.compileToStringMinMaxArguments(pattern, new StringBuilder(), 1, 1);
- NumberStringBuilder output = new NumberStringBuilder();
- output.append((String) outputs[j][0], null);
- new SimpleModifier(compiledPattern, null, false)
- .apply(output, (Integer) outputs[j][1], (Integer) outputs[j][2]);
- String expected = expecteds[j][i];
- String actual = output.toString();
- assert expected.equals(actual);
- }
+ /** TODO: Move this to a test file somewhere, once we figure out what to do with the method. */
+ public static void testFormatAsPrefixSuffix() {
+ String[] patterns = { "{0}", "X{0}Y", "XX{0}YYY", "{0}YY", "XXXX{0}" };
+ Object[][] outputs = { { "", 0, 0 }, { "abcde", 0, 0 }, { "abcde", 2, 2 }, { "abcde", 1, 3 } };
+ String[][] expecteds = { { "", "XY", "XXYYY", "YY", "XXXX" },
+ { "abcde", "XYabcde", "XXYYYabcde", "YYabcde", "XXXXabcde" },
+ { "abcde", "abXYcde", "abXXYYYcde", "abYYcde", "abXXXXcde" },
+ { "abcde", "aXbcYde", "aXXbcYYYde", "abcYYde", "aXXXXbcde" } };
+ for (int i = 0; i < patterns.length; i++) {
+ for (int j = 0; j < outputs.length; j++) {
+ String pattern = patterns[i];
+ String compiledPattern = SimpleFormatterImpl.compileToStringMinMaxArguments(pattern,
+ new StringBuilder(), 1, 1);
+ NumberStringBuilder output = new NumberStringBuilder();
+ output.append((String) outputs[j][0], null);
+ new SimpleModifier(compiledPattern, null, false).apply(output, (Integer) outputs[j][1],
+ (Integer) outputs[j][2]);
+ String expected = expecteds[j][i];
+ String actual = output.toString();
+ assert expected.equals(actual);
+ }
+ }
}
- }
}
*/
@Deprecated
public String getPrefix() {
- return micros.modOuter.getPrefix() + micros.modMiddle.getPrefix() + micros.modInner.getPrefix();
+ NumberStringBuilder temp = new NumberStringBuilder();
+ int length = micros.modOuter.apply(temp, 0, 0);
+ length += micros.modMiddle.apply(temp, 0, length);
+ length += micros.modInner.apply(temp, 0, length);
+ int prefixLength = micros.modOuter.getPrefixLength() + micros.modMiddle.getPrefixLength()
+ + micros.modInner.getPrefixLength();
+ return temp.subSequence(0, prefixLength).toString();
}
/**
*/
@Deprecated
public String getSuffix() {
- return micros.modInner.getSuffix() + micros.modMiddle.getSuffix() + micros.modOuter.getSuffix();
+ NumberStringBuilder temp = new NumberStringBuilder();
+ int length = micros.modOuter.apply(temp, 0, 0);
+ length += micros.modMiddle.apply(temp, 0, length);
+ length += micros.modInner.apply(temp, 0, length);
+ int prefixLength = micros.modOuter.getPrefixLength() + micros.modMiddle.getPrefixLength()
+ + micros.modInner.getPrefixLength();
+ return temp.subSequence(prefixLength, length).toString();
}
/**
}
@Override
- public boolean isStrong() {
- return isStrong;
+ public int getPrefixLength() {
+ return insertPrefix(null, 0);
}
@Override
- public String getPrefix() {
- NumberStringBuilder sb = new NumberStringBuilder(10);
- insertPrefix(sb, 0);
- return sb.toString();
- }
-
- @Override
- public String getSuffix() {
- NumberStringBuilder sb = new NumberStringBuilder(10);
- insertSuffix(sb, 0);
- return sb.toString();
+ public boolean isStrong() {
+ return isStrong;
}
private int insertPrefix(NumberStringBuilder sb, int position) {
}
@Override
- public boolean isStrong() {
- return true;
- }
-
- @Override
- public String getPrefix() {
+ public int getPrefixLength() {
// FIXME: Localized exponent separator location.
- return "";
+ return 0;
}
@Override
- public String getSuffix() {
- // FIXME: Localized exponent separator location.
- NumberStringBuilder temp = new NumberStringBuilder();
- doApply(exponent, temp, 0);
- return temp.toString();
+ public boolean isStrong() {
+ return true;
}
@Override
}
@Override
- public boolean isStrong() {
- return true;
- }
-
- @Override
- public String getPrefix() {
- // FIXME: Localized exponent separator location.
- return "";
+ public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
+ return doApply(exponent, output, rightIndex);
}
@Override
- public String getSuffix() {
+ public int getPrefixLength() {
// FIXME: Localized exponent separator location.
- NumberStringBuilder temp = new NumberStringBuilder();
- doApply(exponent, temp, 0);
- return temp.toString();
+ return 0;
}
@Override
- public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
- return doApply(exponent, output, rightIndex);
+ public boolean isStrong() {
+ return true;
}
}
}
assertEquals(
"Currency on <" + input + ">", curr, AffixPatternUtils.hasCurrencySymbols(input));
- assertEquals("Length on <" + input + ">", length, AffixPatternUtils.unescapedLength(input));
+ assertEquals("Length on <" + input + ">", length, AffixPatternUtils.estimateLength(input));
String actual = unescapeWithDefaults(input);
assertEquals("Output on <" + input + ">", output, actual);
// OK
}
try {
- AffixPatternUtils.unescapedLength(str);
+ AffixPatternUtils.estimateLength(str);
fail("No exception was thrown on an invalid string");
} catch (IllegalArgumentException e) {
// OK
import org.junit.Test;
import com.ibm.icu.impl.number.LdmlPatternInfo;
+import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.MeasureFormat.FormatWidth;
import com.ibm.icu.util.Currency;
FormatWidth.SHORT,
null);
murky.setNumberProperties(false, null);
- assertEquals("a", murky.getPrefix());
- assertEquals("b", murky.getSuffix());
+ assertEquals("a", getPrefix(murky));
+ assertEquals("b", getSuffix(murky));
murky.setPatternAttributes(SignDisplay.ALWAYS, false);
- assertEquals("+a", murky.getPrefix());
- assertEquals("b", murky.getSuffix());
+ assertEquals("+a", getPrefix(murky));
+ assertEquals("b", getSuffix(murky));
murky.setNumberProperties(true, null);
- assertEquals("-a", murky.getPrefix());
- assertEquals("b", murky.getSuffix());
+ assertEquals("-a", getPrefix(murky));
+ assertEquals("b", getSuffix(murky));
murky.setPatternAttributes(SignDisplay.NEVER, false);
- assertEquals("a", murky.getPrefix());
- assertEquals("b", murky.getSuffix());
+ assertEquals("a", getPrefix(murky));
+ assertEquals("b", getSuffix(murky));
murky.setPatternInfo(LdmlPatternInfo.parse("a0b;c-0d"));
murky.setPatternAttributes(SignDisplay.AUTO, false);
murky.setNumberProperties(false, null);
- assertEquals("a", murky.getPrefix());
- assertEquals("b", murky.getSuffix());
+ assertEquals("a", getPrefix(murky));
+ assertEquals("b", getSuffix(murky));
murky.setPatternAttributes(SignDisplay.ALWAYS, false);
- assertEquals("c+", murky.getPrefix());
- assertEquals("d", murky.getSuffix());
+ assertEquals("c+", getPrefix(murky));
+ assertEquals("d", getSuffix(murky));
murky.setNumberProperties(true, null);
- assertEquals("c-", murky.getPrefix());
- assertEquals("d", murky.getSuffix());
+ assertEquals("c-", getPrefix(murky));
+ assertEquals("d", getSuffix(murky));
murky.setPatternAttributes(SignDisplay.NEVER, false);
- assertEquals("c-", murky.getPrefix()); // TODO: What should this behavior be?
- assertEquals("d", murky.getSuffix());
+ assertEquals("c-", getPrefix(murky)); // TODO: What should this behavior be?
+ assertEquals("d", getSuffix(murky));
+ }
+
+ private static String getPrefix(MurkyModifier murky) {
+ NumberStringBuilder nsb = new NumberStringBuilder();
+ murky.apply(nsb, 0, 0);
+ return nsb.subSequence(0, murky.getPrefixLength()).toString();
+ }
+
+ private static String getSuffix(MurkyModifier murky) {
+ NumberStringBuilder nsb = new NumberStringBuilder();
+ murky.apply(nsb, 0, 0);
+ return nsb.subSequence(murky.getPrefixLength(), nsb.length()).toString();
}
}