ICU-13177 Cleaning up Java compact and long names in preparation for C++.
X-SVN-Rev: 40418
This commit is contained in:
parent
33d0dbbb73
commit
c842f7426d
@ -364,6 +364,14 @@ public class ICUResourceBundle extends UResourceBundle {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void getAllItemsWithFallbackNoFail(String path, UResource.Sink sink) {
|
||||||
|
try {
|
||||||
|
getAllItemsWithFallback(path, sink);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
// Quietly ignore the exception.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void getAllItemsWithFallback(String path, UResource.Sink sink)
|
public void getAllItemsWithFallback(String path, UResource.Sink sink)
|
||||||
throws MissingResourceException {
|
throws MissingResourceException {
|
||||||
// Collect existing and parsed key objects into an array of keys,
|
// Collect existing and parsed key objects into an array of keys,
|
||||||
|
@ -140,7 +140,8 @@ class NumberFormatterImpl {
|
|||||||
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(innerPattern);
|
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(innerPattern);
|
||||||
|
|
||||||
// Symbols
|
// Symbols
|
||||||
// NOTE: C++ has a special class, SymbolsWrapper, in MacroProps. Java has all the resolution logic here directly.
|
// NOTE: C++ has a special class, SymbolsWrapper, in MacroProps. Java has all the resolution logic here
|
||||||
|
// directly.
|
||||||
if (macros.symbols == null) {
|
if (macros.symbols == null) {
|
||||||
micros.symbols = DecimalFormatSymbols.getInstance(macros.loc);
|
micros.symbols = DecimalFormatSymbols.getInstance(macros.loc);
|
||||||
} else if (macros.symbols instanceof DecimalFormatSymbols) {
|
} else if (macros.symbols instanceof DecimalFormatSymbols) {
|
||||||
@ -238,7 +239,9 @@ class NumberFormatterImpl {
|
|||||||
// Lazily create PluralRules
|
// Lazily create PluralRules
|
||||||
rules = PluralRules.forLocale(macros.loc);
|
rules = PluralRules.forLocale(macros.loc);
|
||||||
}
|
}
|
||||||
CompactType compactType = (macros.unit instanceof Currency) ? CompactType.CURRENCY : CompactType.DECIMAL;
|
CompactType compactType = (macros.unit instanceof Currency && macros.unitWidth != UnitWidth.FULL_NAME)
|
||||||
|
? CompactType.CURRENCY
|
||||||
|
: CompactType.DECIMAL;
|
||||||
chain = ((CompactNotation) macros.notation).withLocaleData(macros.loc, compactType, rules,
|
chain = ((CompactNotation) macros.notation).withLocaleData(macros.loc, compactType, rules,
|
||||||
safe ? patternMod : null, chain);
|
safe ? patternMod : null, chain);
|
||||||
}
|
}
|
||||||
|
@ -58,25 +58,39 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
|
|
||||||
/* package-private */ MicroPropsGenerator withLocaleData(DecimalFormatSymbols symbols, boolean build,
|
/* package-private */ MicroPropsGenerator withLocaleData(DecimalFormatSymbols symbols, boolean build,
|
||||||
MicroPropsGenerator parent) {
|
MicroPropsGenerator parent) {
|
||||||
return new MurkyScientificHandler(symbols, build, parent);
|
return new ScientificHandler(this, symbols, build, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MurkyScientificHandler implements MicroPropsGenerator, MultiplierProducer, Modifier {
|
// NOTE: The object lifecycle of ScientificModifier and ScientificHandler differ greatly in Java and C++.
|
||||||
|
//
|
||||||
|
// During formatting, we need to provide an object with state (the exponent) as the inner modifier.
|
||||||
|
//
|
||||||
|
// In Java, where the priority is put on reducing object creations, the unsafe code path re-uses the
|
||||||
|
// ScientificHandler as a ScientificModifier, and the safe code path pre-computes 25 ScientificModifier
|
||||||
|
// instances. This scheme reduces the number of object creations by 1 in both safe and unsafe.
|
||||||
|
//
|
||||||
|
// In C++, MicroProps provides a pre-allocated ScientificModifier, and ScientificHandler simply populates
|
||||||
|
// the state (the exponent) into that ScientificModifier. There is no difference between safe and unsafe.
|
||||||
|
|
||||||
|
private static class ScientificHandler implements MicroPropsGenerator, MultiplierProducer, Modifier {
|
||||||
|
|
||||||
|
final ScientificNotation notation;
|
||||||
final DecimalFormatSymbols symbols;
|
final DecimalFormatSymbols symbols;
|
||||||
final ImmutableScientificModifier[] precomputedMods;
|
final ScientificModifier[] precomputedMods;
|
||||||
final MicroPropsGenerator parent;
|
final MicroPropsGenerator parent;
|
||||||
/* unsafe */ int exponent;
|
/* unsafe */ int exponent;
|
||||||
|
|
||||||
private MurkyScientificHandler(DecimalFormatSymbols symbols, boolean safe, MicroPropsGenerator parent) {
|
private ScientificHandler(ScientificNotation notation, DecimalFormatSymbols symbols, boolean safe,
|
||||||
|
MicroPropsGenerator parent) {
|
||||||
|
this.notation = notation;
|
||||||
this.symbols = symbols;
|
this.symbols = symbols;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
|
||||||
if (safe) {
|
if (safe) {
|
||||||
// Pre-build the modifiers for exponents -12 through 12
|
// Pre-build the modifiers for exponents -12 through 12
|
||||||
precomputedMods = new ImmutableScientificModifier[25];
|
precomputedMods = new ScientificModifier[25];
|
||||||
for (int i = -12; i <= 12; i++) {
|
for (int i = -12; i <= 12; i++) {
|
||||||
precomputedMods[i + 12] = new ImmutableScientificModifier(i);
|
precomputedMods[i + 12] = new ScientificModifier(i, this);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
precomputedMods = null;
|
precomputedMods = null;
|
||||||
@ -91,9 +105,9 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
// Treat zero as if it had magnitude 0
|
// Treat zero as if it had magnitude 0
|
||||||
int exponent;
|
int exponent;
|
||||||
if (quantity.isZero()) {
|
if (quantity.isZero()) {
|
||||||
if (requireMinInt && micros.rounding instanceof SignificantRounderImpl) {
|
if (notation.requireMinInt && micros.rounding instanceof SignificantRounderImpl) {
|
||||||
// Show "00.000E0" on pattern "00.000E0"
|
// Show "00.000E0" on pattern "00.000E0"
|
||||||
((SignificantRounderImpl) micros.rounding).apply(quantity, engineeringInterval);
|
((SignificantRounderImpl) micros.rounding).apply(quantity, notation.engineeringInterval);
|
||||||
exponent = 0;
|
exponent = 0;
|
||||||
} else {
|
} else {
|
||||||
micros.rounding.apply(quantity);
|
micros.rounding.apply(quantity);
|
||||||
@ -109,7 +123,7 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
micros.modInner = precomputedMods[exponent + 12];
|
micros.modInner = precomputedMods[exponent + 12];
|
||||||
} else if (precomputedMods != null) {
|
} else if (precomputedMods != null) {
|
||||||
// Safe code path B
|
// Safe code path B
|
||||||
micros.modInner = new ImmutableScientificModifier(exponent);
|
micros.modInner = new ScientificModifier(exponent, this);
|
||||||
} else {
|
} else {
|
||||||
// Unsafe code path: mutates the object and re-uses it as a Modifier!
|
// Unsafe code path: mutates the object and re-uses it as a Modifier!
|
||||||
this.exponent = exponent;
|
this.exponent = exponent;
|
||||||
@ -124,9 +138,9 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMultiplier(int magnitude) {
|
public int getMultiplier(int magnitude) {
|
||||||
int interval = engineeringInterval;
|
int interval = notation.engineeringInterval;
|
||||||
int digitsShown;
|
int digitsShown;
|
||||||
if (requireMinInt) {
|
if (notation.requireMinInt) {
|
||||||
// For patterns like "000.00E0" and ".00E0"
|
// For patterns like "000.00E0" and ".00E0"
|
||||||
digitsShown = interval;
|
digitsShown = interval;
|
||||||
} else if (interval <= 1) {
|
} else if (interval <= 1) {
|
||||||
@ -141,7 +155,7 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPrefixLength() {
|
public int getPrefixLength() {
|
||||||
// FIXME: Localized exponent separator location.
|
// TODO: Localized exponent separator location.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +167,7 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStrong() {
|
public boolean isStrong() {
|
||||||
|
// Scientific is always strong
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,36 +181,39 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
int i = rightIndex;
|
int i = rightIndex;
|
||||||
// Append the exponent separator and sign
|
// Append the exponent separator and sign
|
||||||
i += output.insert(i, symbols.getExponentSeparator(), NumberFormat.Field.EXPONENT_SYMBOL);
|
i += output.insert(i, symbols.getExponentSeparator(), NumberFormat.Field.EXPONENT_SYMBOL);
|
||||||
if (exponent < 0 && exponentSignDisplay != SignDisplay.NEVER) {
|
if (exponent < 0 && notation.exponentSignDisplay != SignDisplay.NEVER) {
|
||||||
i += output.insert(i, symbols.getMinusSignString(), NumberFormat.Field.EXPONENT_SIGN);
|
i += output.insert(i, symbols.getMinusSignString(), NumberFormat.Field.EXPONENT_SIGN);
|
||||||
} else if (exponentSignDisplay == SignDisplay.ALWAYS) {
|
} else if (notation.exponentSignDisplay == SignDisplay.ALWAYS) {
|
||||||
i += output.insert(i, symbols.getPlusSignString(), NumberFormat.Field.EXPONENT_SIGN);
|
i += output.insert(i, symbols.getPlusSignString(), NumberFormat.Field.EXPONENT_SIGN);
|
||||||
}
|
}
|
||||||
// Append the exponent digits (using a simple inline algorithm)
|
// Append the exponent digits (using a simple inline algorithm)
|
||||||
int disp = Math.abs(exponent);
|
int disp = Math.abs(exponent);
|
||||||
for (int j = 0; j < minExponentDigits || disp > 0; j++, disp /= 10) {
|
for (int j = 0; j < notation.minExponentDigits || disp > 0; j++, disp /= 10) {
|
||||||
int d = disp % 10;
|
int d = disp % 10;
|
||||||
String digitString = symbols.getDigitStringsLocal()[d];
|
String digitString = symbols.getDigitStringsLocal()[d];
|
||||||
i += output.insert(i - j, digitString, NumberFormat.Field.EXPONENT);
|
i += output.insert(i - j, digitString, NumberFormat.Field.EXPONENT);
|
||||||
}
|
}
|
||||||
return i - rightIndex;
|
return i - rightIndex;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ImmutableScientificModifier implements Modifier {
|
private static class ScientificModifier implements Modifier {
|
||||||
final int exponent;
|
final int exponent;
|
||||||
|
final ScientificHandler handler;
|
||||||
|
|
||||||
ImmutableScientificModifier(int exponent) {
|
ScientificModifier(int exponent, ScientificHandler handler) {
|
||||||
this.exponent = exponent;
|
this.exponent = exponent;
|
||||||
|
this.handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
|
public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
|
||||||
return doApply(exponent, output, rightIndex);
|
return handler.doApply(exponent, output, rightIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPrefixLength() {
|
public int getPrefixLength() {
|
||||||
// FIXME: Localized exponent separator location.
|
// TODO: Localized exponent separator location.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,8 +225,8 @@ public class ScientificNotation extends Notation implements Cloneable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStrong() {
|
public boolean isStrong() {
|
||||||
|
// Scientific is always strong
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -5,7 +5,6 @@ package newapi.impl;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.MissingResourceException;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.ibm.icu.impl.ICUData;
|
import com.ibm.icu.impl.ICUData;
|
||||||
@ -20,28 +19,48 @@ import com.ibm.icu.util.UResourceBundle;
|
|||||||
|
|
||||||
public class CompactData implements MultiplierProducer {
|
public class CompactData implements MultiplierProducer {
|
||||||
|
|
||||||
public static CompactData getInstance(
|
public static CompactData getInstance(ULocale locale, CompactType compactType, CompactStyle compactStyle) {
|
||||||
ULocale locale, CompactType compactType, CompactStyle compactStyle) {
|
|
||||||
// TODO: Add a data cache? It would be keyed by locale, compact type, and compact style.
|
// TODO: Add a data cache? It would be keyed by locale, compact type, and compact style.
|
||||||
CompactData data = new CompactData();
|
CompactData data = new CompactData();
|
||||||
CompactDataSink sink = new CompactDataSink(data, compactType, compactStyle);
|
CompactDataSink sink = new CompactDataSink(data);
|
||||||
String nsName = NumberingSystem.getInstance(locale).getName();
|
String nsName = NumberingSystem.getInstance(locale).getName();
|
||||||
ICUResourceBundle rb =
|
ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
|
||||||
(ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
|
|
||||||
CompactData.internalPopulateData(nsName, rb, sink, data);
|
// Fall back to latn numbering system and/or short compact style.
|
||||||
if (data.isEmpty() && compactStyle == CompactStyle.LONG) {
|
String resourceKey = getResourceBundleKey(nsName, compactStyle, compactType);
|
||||||
// No long data is available; load short data instead
|
rb.getAllItemsWithFallbackNoFail(resourceKey, sink);
|
||||||
sink.compactStyle = CompactStyle.SHORT;
|
if (data.isEmpty() && !nsName.equals("latn")) {
|
||||||
CompactData.internalPopulateData(nsName, rb, sink, data);
|
resourceKey = getResourceBundleKey("latn", compactStyle, compactType);
|
||||||
|
rb.getAllItemsWithFallbackNoFail(resourceKey, sink);
|
||||||
}
|
}
|
||||||
|
if (data.isEmpty() && compactStyle != CompactStyle.SHORT) {
|
||||||
|
resourceKey = getResourceBundleKey(nsName, CompactStyle.SHORT, compactType);
|
||||||
|
rb.getAllItemsWithFallbackNoFail(resourceKey, sink);
|
||||||
|
}
|
||||||
|
if (data.isEmpty() && !nsName.equals("latn") && compactStyle != CompactStyle.SHORT) {
|
||||||
|
resourceKey = getResourceBundleKey("latn", CompactStyle.SHORT, compactType);
|
||||||
|
rb.getAllItemsWithFallbackNoFail(resourceKey, sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The last fallback is guaranteed to return data.
|
||||||
|
assert (!data.isEmpty());
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompactData getInstance(
|
/** Returns a string like "NumberElements/latn/patternsShort/decimalFormat". */
|
||||||
Map<String, Map<String, String>> powersToPluralsToPatterns) {
|
private static String getResourceBundleKey(String nsName, CompactStyle compactStyle, CompactType compactType) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("NumberElements/");
|
||||||
|
sb.append(nsName);
|
||||||
|
sb.append(compactStyle == CompactStyle.SHORT ? "/patternsShort" : "/patternsLong");
|
||||||
|
sb.append(compactType == CompactType.DECIMAL ? "/decimalFormat" : "/currencyFormat");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Java-only method used by CLDR tooling. */
|
||||||
|
public static CompactData getInstance(Map<String, Map<String, String>> powersToPluralsToPatterns) {
|
||||||
CompactData data = new CompactData();
|
CompactData data = new CompactData();
|
||||||
for (Map.Entry<String, Map<String, String>> magnitudeEntry :
|
for (Map.Entry<String, Map<String, String>> magnitudeEntry : powersToPluralsToPatterns.entrySet()) {
|
||||||
powersToPluralsToPatterns.entrySet()) {
|
|
||||||
byte magnitude = (byte) (magnitudeEntry.getKey().length() - 1);
|
byte magnitude = (byte) (magnitudeEntry.getKey().length() - 1);
|
||||||
for (Map.Entry<String, String> pluralEntry : magnitudeEntry.getValue().entrySet()) {
|
for (Map.Entry<String, String> pluralEntry : magnitudeEntry.getValue().entrySet()) {
|
||||||
StandardPlural plural = StandardPlural.fromString(pluralEntry.getKey().toString());
|
StandardPlural plural = StandardPlural.fromString(pluralEntry.getKey().toString());
|
||||||
@ -56,21 +75,6 @@ public class CompactData implements MultiplierProducer {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void internalPopulateData(
|
|
||||||
String nsName, ICUResourceBundle rb, CompactDataSink sink, CompactData data) {
|
|
||||||
try {
|
|
||||||
rb.getAllItemsWithFallback("NumberElements/" + nsName, sink);
|
|
||||||
} catch (MissingResourceException e) {
|
|
||||||
// Fall back to latn
|
|
||||||
}
|
|
||||||
if (data.isEmpty() && !nsName.equals("latn")) {
|
|
||||||
rb.getAllItemsWithFallback("NumberElements/latn", sink);
|
|
||||||
}
|
|
||||||
if (sink.exception != null) {
|
|
||||||
throw sink.exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A dummy object used when a "0" compact decimal entry is encountered. This is necessary
|
// A dummy object used when a "0" compact decimal entry is encountered. This is necessary
|
||||||
// in order to prevent falling back to root. Object equality ("==") is intended.
|
// in order to prevent falling back to root. Object equality ("==") is intended.
|
||||||
private static final String USE_FALLBACK = "<USE FALLBACK>";
|
private static final String USE_FALLBACK = "<USE FALLBACK>";
|
||||||
@ -116,7 +120,9 @@ public class CompactData implements MultiplierProducer {
|
|||||||
}
|
}
|
||||||
multipliers[magnitude] = multiplier;
|
multipliers[magnitude] = multiplier;
|
||||||
isEmpty = false;
|
isEmpty = false;
|
||||||
if (magnitude > largestMagnitude) largestMagnitude = magnitude;
|
if (magnitude > largestMagnitude) {
|
||||||
|
largestMagnitude = magnitude;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPattern(int magnitude, StandardPlural plural) {
|
public String getPattern(int magnitude, StandardPlural plural) {
|
||||||
@ -131,7 +137,7 @@ public class CompactData implements MultiplierProducer {
|
|||||||
// Fall back to "other" plural variant
|
// Fall back to "other" plural variant
|
||||||
patternString = patterns[getIndex(magnitude, StandardPlural.OTHER)];
|
patternString = patterns[getIndex(magnitude, StandardPlural.OTHER)];
|
||||||
}
|
}
|
||||||
if (patternString == USE_FALLBACK) {
|
if (patternString == USE_FALLBACK) { // == is intended
|
||||||
// Return null if USE_FALLBACK is present
|
// Return null if USE_FALLBACK is present
|
||||||
patternString = null;
|
patternString = null;
|
||||||
}
|
}
|
||||||
@ -154,7 +160,8 @@ public class CompactData implements MultiplierProducer {
|
|||||||
private void setPattern(String patternString, int magnitude, StandardPlural plural) {
|
private void setPattern(String patternString, int magnitude, StandardPlural plural) {
|
||||||
patterns[getIndex(magnitude, plural)] = patternString;
|
patterns[getIndex(magnitude, plural)] = patternString;
|
||||||
isEmpty = false;
|
isEmpty = false;
|
||||||
if (magnitude > largestMagnitude) largestMagnitude = magnitude;
|
if (magnitude > largestMagnitude)
|
||||||
|
largestMagnitude = magnitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setNoFallback(int magnitude, StandardPlural plural) {
|
private void setNoFallback(int magnitude, StandardPlural plural) {
|
||||||
@ -168,55 +175,22 @@ public class CompactData implements MultiplierProducer {
|
|||||||
private static final class CompactDataSink extends UResource.Sink {
|
private static final class CompactDataSink extends UResource.Sink {
|
||||||
|
|
||||||
CompactData data;
|
CompactData data;
|
||||||
CompactStyle compactStyle;
|
|
||||||
CompactType compactType;
|
|
||||||
IllegalArgumentException exception;
|
|
||||||
|
|
||||||
/*
|
public CompactDataSink(CompactData data) {
|
||||||
* NumberElements{ <-- top (numbering system table)
|
|
||||||
* latn{ <-- patternsTable (one per numbering system)
|
|
||||||
* patternsLong{ <-- formatsTable (one per pattern)
|
|
||||||
* decimalFormat{ <-- powersOfTenTable (one per format)
|
|
||||||
* 1000{ <-- pluralVariantsTable (one per power of ten)
|
|
||||||
* one{"0 thousand"} <-- plural variant and template
|
|
||||||
*/
|
|
||||||
|
|
||||||
public CompactDataSink(CompactData data, CompactType compactType, CompactStyle compactStyle) {
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.compactType = compactType;
|
|
||||||
this.compactStyle = compactStyle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(UResource.Key key, UResource.Value value, boolean isRoot) {
|
public void put(UResource.Key key, UResource.Value value, boolean isRoot) {
|
||||||
UResource.Table patternsTable = value.getTable();
|
|
||||||
for (int i1 = 0; patternsTable.getKeyAndValue(i1, key, value); ++i1) {
|
|
||||||
if (key.contentEquals("patternsShort") && compactStyle == CompactStyle.SHORT) {
|
|
||||||
} else if (key.contentEquals("patternsLong") && compactStyle == CompactStyle.LONG) {
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// traverse into the table of formats
|
|
||||||
UResource.Table formatsTable = value.getTable();
|
|
||||||
for (int i2 = 0; formatsTable.getKeyAndValue(i2, key, value); ++i2) {
|
|
||||||
if (key.contentEquals("decimalFormat") && compactType == CompactType.DECIMAL) {
|
|
||||||
} else if (key.contentEquals("currencyFormat") && compactType == CompactType.CURRENCY) {
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// traverse into the table of powers of ten
|
// traverse into the table of powers of ten
|
||||||
UResource.Table powersOfTenTable = value.getTable();
|
UResource.Table powersOfTenTable = value.getTable();
|
||||||
for (int i3 = 0; powersOfTenTable.getKeyAndValue(i3, key, value); ++i3) {
|
for (int i3 = 0; powersOfTenTable.getKeyAndValue(i3, key, value); ++i3) {
|
||||||
|
|
||||||
// Assumes that the keys are always of the form "10000" where the magnitude is the
|
// Assumes that the keys are always of the form "10000" where the magnitude is the
|
||||||
// length of the key minus one
|
// length of the key minus one. We expect magnitudes to be less than MAX_DIGITS.
|
||||||
byte magnitude = (byte) (key.length() - 1);
|
byte magnitude = (byte) (key.length() - 1);
|
||||||
byte multiplier = (byte) data.getMultiplierDirect(magnitude);
|
byte multiplier = (byte) data.getMultiplierDirect(magnitude);
|
||||||
|
assert magnitude < MAX_DIGITS;
|
||||||
// Silently ignore divisors that are too big.
|
|
||||||
if (magnitude >= CompactData.MAX_DIGITS) continue;
|
|
||||||
|
|
||||||
// Iterate over the plural variants ("one", "other", etc)
|
// Iterate over the plural variants ("one", "other", etc)
|
||||||
UResource.Table pluralVariantsTable = value.getTable();
|
UResource.Table pluralVariantsTable = value.getTable();
|
||||||
@ -251,12 +225,6 @@ public class CompactData implements MultiplierProducer {
|
|||||||
|
|
||||||
data.setMultiplier(magnitude, multiplier);
|
data.setMultiplier(magnitude, multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want only one table of compact decimal formats, so if we get here, stop consuming.
|
|
||||||
// The data.isEmpty() check will prevent further bundles from being traversed.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,9 @@ public class LongNameHandler implements MicroPropsGenerator {
|
|||||||
String pluralKeyword = e.getKey();
|
String pluralKeyword = e.getKey();
|
||||||
StandardPlural plural = StandardPlural.fromString(e.getKey());
|
StandardPlural plural = StandardPlural.fromString(e.getKey());
|
||||||
String longName = currency.getName(loc, Currency.PLURAL_LONG_NAME, pluralKeyword, null);
|
String longName = currency.getName(loc, Currency.PLURAL_LONG_NAME, pluralKeyword, null);
|
||||||
String simpleFormat = e.getValue(); // e.g., "{0} {1}"
|
String simpleFormat = e.getValue();
|
||||||
|
// Example pattern from data: "{0} {1}"
|
||||||
|
// Example output after find-and-replace: "{0} US dollars"
|
||||||
simpleFormat = simpleFormat.replace("{1}", longName);
|
simpleFormat = simpleFormat.replace("{1}", longName);
|
||||||
String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 1, 1);
|
String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 1, 1);
|
||||||
SimpleModifier mod = new SimpleModifier(compiled, Field.CURRENCY, false);
|
SimpleModifier mod = new SimpleModifier(compiled, Field.CURRENCY, false);
|
||||||
|
@ -186,13 +186,50 @@ public class NumberFormatterTest {
|
|||||||
"$0.0088",
|
"$0.0088",
|
||||||
"$0");
|
"$0");
|
||||||
|
|
||||||
|
assertFormatDescending(
|
||||||
|
"Compact Short with ISO Currency",
|
||||||
|
"C $USD unit-width=ISO_CODE",
|
||||||
|
NumberFormatter.with()
|
||||||
|
.notation(Notation.compactShort())
|
||||||
|
.unit(USD)
|
||||||
|
.unitWidth(UnitWidth.ISO_CODE),
|
||||||
|
ULocale.ENGLISH,
|
||||||
|
"USD 88K",
|
||||||
|
"USD 8.8K",
|
||||||
|
"USD 876",
|
||||||
|
"USD 88",
|
||||||
|
"USD 8.8",
|
||||||
|
"USD 0.88",
|
||||||
|
"USD 0.088",
|
||||||
|
"USD 0.0088",
|
||||||
|
"USD 0");
|
||||||
|
|
||||||
|
assertFormatDescending(
|
||||||
|
"Compact Short with Long Name Currency",
|
||||||
|
"C $USD unit-width=FULL_NAME",
|
||||||
|
NumberFormatter.with()
|
||||||
|
.notation(Notation.compactShort())
|
||||||
|
.unit(USD)
|
||||||
|
.unitWidth(UnitWidth.FULL_NAME),
|
||||||
|
ULocale.ENGLISH,
|
||||||
|
"88K US dollars",
|
||||||
|
"8.8K US dollars",
|
||||||
|
"876 US dollars",
|
||||||
|
"88 US dollars",
|
||||||
|
"8.8 US dollars",
|
||||||
|
"0.88 US dollars",
|
||||||
|
"0.088 US dollars",
|
||||||
|
"0.0088 US dollars",
|
||||||
|
"0 US dollars");
|
||||||
|
|
||||||
// Note: Most locales don't have compact long currency, so this currently falls back to short.
|
// Note: Most locales don't have compact long currency, so this currently falls back to short.
|
||||||
|
// This test case should be fixed when proper compact long currency patterns are added.
|
||||||
assertFormatDescending(
|
assertFormatDescending(
|
||||||
"Compact Long Currency",
|
"Compact Long Currency",
|
||||||
"CC $USD",
|
"CC $USD",
|
||||||
NumberFormatter.with().notation(Notation.compactLong()).unit(USD),
|
NumberFormatter.with().notation(Notation.compactLong()).unit(USD),
|
||||||
ULocale.ENGLISH,
|
ULocale.ENGLISH,
|
||||||
"$88K",
|
"$88K", // should be something like "$88 thousand"
|
||||||
"$8.8K",
|
"$8.8K",
|
||||||
"$876",
|
"$876",
|
||||||
"$88",
|
"$88",
|
||||||
@ -202,6 +239,45 @@ public class NumberFormatterTest {
|
|||||||
"$0.0088",
|
"$0.0088",
|
||||||
"$0");
|
"$0");
|
||||||
|
|
||||||
|
// Note: Most locales don't have compact long currency, so this currently falls back to short.
|
||||||
|
// This test case should be fixed when proper compact long currency patterns are added.
|
||||||
|
assertFormatDescending(
|
||||||
|
"Compact Long with ISO Currency",
|
||||||
|
"CC $USD unit-width=ISO_CODE",
|
||||||
|
NumberFormatter.with()
|
||||||
|
.notation(Notation.compactLong())
|
||||||
|
.unit(USD)
|
||||||
|
.unitWidth(UnitWidth.ISO_CODE),
|
||||||
|
ULocale.ENGLISH,
|
||||||
|
"USD 88K", // should be something like "USD 88 thousand"
|
||||||
|
"USD 8.8K",
|
||||||
|
"USD 876",
|
||||||
|
"USD 88",
|
||||||
|
"USD 8.8",
|
||||||
|
"USD 0.88",
|
||||||
|
"USD 0.088",
|
||||||
|
"USD 0.0088",
|
||||||
|
"USD 0");
|
||||||
|
|
||||||
|
// TODO: This behavior could be improved and should be revisited.
|
||||||
|
assertFormatDescending(
|
||||||
|
"Compact Long with Long Name Currency",
|
||||||
|
"CC $USD unit-width=FULL_NAME",
|
||||||
|
NumberFormatter.with()
|
||||||
|
.notation(Notation.compactLong())
|
||||||
|
.unit(USD)
|
||||||
|
.unitWidth(UnitWidth.FULL_NAME),
|
||||||
|
ULocale.ENGLISH,
|
||||||
|
"88 thousand US dollars",
|
||||||
|
"8.8 thousand US dollars",
|
||||||
|
"876 US dollars",
|
||||||
|
"88 US dollars",
|
||||||
|
"8.8 US dollars",
|
||||||
|
"0.88 US dollars",
|
||||||
|
"0.088 US dollars",
|
||||||
|
"0.0088 US dollars",
|
||||||
|
"0 US dollars");
|
||||||
|
|
||||||
assertFormatSingle(
|
assertFormatSingle(
|
||||||
"Compact Plural One",
|
"Compact Plural One",
|
||||||
"CC",
|
"CC",
|
||||||
|
Loading…
Reference in New Issue
Block a user