mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-20230 Implementing COMPACT field.
Adds some plumbing to allow MutablePatternModifier to set fields, and otherwise builds upon the infrastructure from the previous commit to add the MEASURE_UNIT field.
This commit is contained in:
parent
ee9c0b944c
commit
c0799c141b
19 changed files with 303 additions and 37 deletions
|
@ -158,7 +158,7 @@ Field AffixUtils::getFieldForType(AffixPatternType type) {
|
|||
|
||||
int32_t
|
||||
AffixUtils::unescape(const UnicodeString &affixPattern, NumberStringBuilder &output, int32_t position,
|
||||
const SymbolProvider &provider, UErrorCode &status) {
|
||||
const SymbolProvider &provider, Field field, UErrorCode &status) {
|
||||
int32_t length = 0;
|
||||
AffixTag tag;
|
||||
while (hasNext(tag, affixPattern)) {
|
||||
|
@ -171,7 +171,7 @@ AffixUtils::unescape(const UnicodeString &affixPattern, NumberStringBuilder &out
|
|||
length += output.insert(
|
||||
position + length, provider.getSymbol(tag.type), getFieldForType(tag.type), status);
|
||||
} else {
|
||||
length += output.insertCodePoint(position + length, tag.codePoint, UNUM_FIELD_COUNT, status);
|
||||
length += output.insertCodePoint(position + length, tag.codePoint, field, status);
|
||||
}
|
||||
}
|
||||
return length;
|
||||
|
|
|
@ -144,7 +144,8 @@ class U_I18N_API AffixUtils {
|
|||
* @param provider An object to generate locale symbols.
|
||||
*/
|
||||
static int32_t unescape(const UnicodeString& affixPattern, NumberStringBuilder& output,
|
||||
int32_t position, const SymbolProvider& provider, UErrorCode& status);
|
||||
int32_t position, const SymbolProvider& provider, Field field,
|
||||
UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Sames as {@link #unescape}, but only calculates the code point count. More efficient than {@link #unescape}
|
||||
|
|
|
@ -260,7 +260,7 @@ void CompactHandler::precomputeAllModifiers(MutablePatternModifier &buildReferen
|
|||
ParsedPatternInfo patternInfo;
|
||||
PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
buildReference.setPatternInfo(&patternInfo);
|
||||
buildReference.setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD);
|
||||
info.mod = buildReference.createImmutable(status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
info.patternString = patternString;
|
||||
|
@ -310,7 +310,7 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr
|
|||
ParsedPatternInfo &patternInfo = const_cast<CompactHandler *>(this)->unsafePatternInfo;
|
||||
PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
|
||||
static_cast<MutablePatternModifier*>(const_cast<Modifier*>(micros.modMiddle))
|
||||
->setPatternInfo(&patternInfo);
|
||||
->setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD);
|
||||
}
|
||||
|
||||
// We already performed rounding. Do not perform it again.
|
||||
|
|
|
@ -344,7 +344,8 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
fPatternModifier.adoptInstead(patternModifier);
|
||||
patternModifier->setPatternInfo(
|
||||
macros.affixProvider != nullptr ? macros.affixProvider
|
||||
: static_cast<const AffixPatternProvider*>(fPatternInfo.getAlias()));
|
||||
: static_cast<const AffixPatternProvider*>(fPatternInfo.getAlias()),
|
||||
UNUM_FIELD_COUNT);
|
||||
patternModifier->setPatternAttributes(fMicros.sign, isPermille);
|
||||
if (patternModifier->needsPlurals()) {
|
||||
patternModifier->setSymbols(
|
||||
|
|
|
@ -23,13 +23,14 @@ AffixPatternProvider::~AffixPatternProvider() = default;
|
|||
MutablePatternModifier::MutablePatternModifier(bool isStrong)
|
||||
: fStrong(isStrong) {}
|
||||
|
||||
void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo) {
|
||||
void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo, Field field) {
|
||||
fPatternInfo = patternInfo;
|
||||
fField = field;
|
||||
}
|
||||
|
||||
void MutablePatternModifier::setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille) {
|
||||
fSignDisplay = signDisplay;
|
||||
this->perMilleReplacesPercent = perMille;
|
||||
fPerMilleReplacesPercent = perMille;
|
||||
}
|
||||
|
||||
void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols,
|
||||
|
@ -255,20 +256,20 @@ bool MutablePatternModifier::semanticallyEquivalent(const Modifier& other) const
|
|||
|
||||
int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder& sb, int position, UErrorCode& status) {
|
||||
prepareAffix(true);
|
||||
int length = AffixUtils::unescape(currentAffix, sb, position, *this, status);
|
||||
int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status);
|
||||
return length;
|
||||
}
|
||||
|
||||
int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder& sb, int position, UErrorCode& status) {
|
||||
prepareAffix(false);
|
||||
int length = AffixUtils::unescape(currentAffix, sb, position, *this, status);
|
||||
int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status);
|
||||
return length;
|
||||
}
|
||||
|
||||
/** This method contains the heart of the logic for rendering LDML affix strings. */
|
||||
void MutablePatternModifier::prepareAffix(bool isPrefix) {
|
||||
PatternStringUtils::patternInfoToStringBuilder(
|
||||
*fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, perMilleReplacesPercent, currentAffix);
|
||||
*fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, fPerMilleReplacesPercent, currentAffix);
|
||||
}
|
||||
|
||||
UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const {
|
||||
|
|
|
@ -95,8 +95,11 @@ class U_I18N_API MutablePatternModifier
|
|||
* Sets a reference to the parsed decimal format pattern, usually obtained from
|
||||
* {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is
|
||||
* accepted.
|
||||
*
|
||||
* @param field
|
||||
* Which field to use for literal characters in the pattern.
|
||||
*/
|
||||
void setPatternInfo(const AffixPatternProvider *patternInfo);
|
||||
void setPatternInfo(const AffixPatternProvider *patternInfo, Field field);
|
||||
|
||||
/**
|
||||
* Sets attributes that imply changes to the literal interpretation of the pattern string affixes.
|
||||
|
@ -203,8 +206,9 @@ class U_I18N_API MutablePatternModifier
|
|||
|
||||
// Pattern details (initialized in setPatternInfo and setPatternAttributes)
|
||||
const AffixPatternProvider *fPatternInfo;
|
||||
Field fField;
|
||||
UNumberSignDisplay fSignDisplay;
|
||||
bool perMilleReplacesPercent;
|
||||
bool fPerMilleReplacesPercent;
|
||||
|
||||
// Symbol details (initialized in setSymbols)
|
||||
const DecimalFormatSymbols *fSymbols;
|
||||
|
|
|
@ -239,6 +239,8 @@ public:
|
|||
kSignField = UNUM_SIGN_FIELD,
|
||||
/** @draft ICU 64 */
|
||||
kMeasureUnitField = UNUM_MEASURE_UNIT_FIELD,
|
||||
/** @draft ICU 64 */
|
||||
kCompactField = UNUM_COMPACT_FIELD,
|
||||
|
||||
/**
|
||||
* These constants are provided for backwards compatibility only.
|
||||
|
|
|
@ -377,6 +377,9 @@ typedef enum UNumberFormatFields {
|
|||
UNUM_SIGN_FIELD,
|
||||
/** @draft ICU 64 */
|
||||
UNUM_MEASURE_UNIT_FIELD,
|
||||
/** @draft ICU 64 */
|
||||
UNUM_COMPACT_FIELD,
|
||||
|
||||
#ifndef U_HIDE_DEPRECATED_API
|
||||
/**
|
||||
* One more than the highest normal UNumberFormatFields value.
|
||||
|
|
|
@ -223,7 +223,7 @@ void AffixUtilsTest::testUnescapeWithSymbolProvider() {
|
|||
UnicodeString input(cas[0]);
|
||||
UnicodeString expected(cas[1]);
|
||||
sb.clear();
|
||||
AffixUtils::unescape(input, sb, 0, provider, status);
|
||||
AffixUtils::unescape(input, sb, 0, provider, UNUM_FIELD_COUNT, status);
|
||||
assertSuccess("Spot 1", status);
|
||||
assertEquals(input, expected, sb.toUnicodeString());
|
||||
assertEquals(input, expected, sb.toTempUnicodeString());
|
||||
|
@ -233,7 +233,7 @@ void AffixUtilsTest::testUnescapeWithSymbolProvider() {
|
|||
sb.clear();
|
||||
sb.append(u"abcdefg", UNUM_FIELD_COUNT, status);
|
||||
assertSuccess("Spot 2", status);
|
||||
AffixUtils::unescape(u"-+%", sb, 4, provider, status);
|
||||
AffixUtils::unescape(u"-+%", sb, 4, provider, UNUM_FIELD_COUNT, status);
|
||||
assertSuccess("Spot 3", status);
|
||||
assertEquals(u"Symbol provider into middle", u"abcd123efg", sb.toUnicodeString());
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ void AffixUtilsTest::testUnescapeWithSymbolProvider() {
|
|||
UnicodeString AffixUtilsTest::unescapeWithDefaults(const SymbolProvider &defaultProvider,
|
||||
UnicodeString input, UErrorCode &status) {
|
||||
NumberStringBuilder nsb;
|
||||
int32_t length = AffixUtils::unescape(input, nsb, 0, defaultProvider, status);
|
||||
int32_t length = AffixUtils::unescape(input, nsb, 0, defaultProvider, UNUM_FIELD_COUNT, status);
|
||||
assertEquals("Return value of unescape", nsb.length(), length);
|
||||
return nsb.toUnicodeString();
|
||||
}
|
||||
|
|
|
@ -2349,6 +2349,130 @@ void NumberFormatterApiTest::fieldPositionCoverage() {
|
|||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
}
|
||||
|
||||
{
|
||||
const char16_t* message = u"Compact field basic";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
u"compact-short",
|
||||
NumberFormatter::with().notation(Notation::compactShort()),
|
||||
Locale::getUS(),
|
||||
65000,
|
||||
u"65K");
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_INTEGER_FIELD, 0, 2},
|
||||
{UNUM_COMPACT_FIELD, 2, 3}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
}
|
||||
|
||||
{
|
||||
const char16_t* message = u"Compact field with spaces";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
u"compact-long",
|
||||
NumberFormatter::with().notation(Notation::compactLong()),
|
||||
Locale::getUS(),
|
||||
65000,
|
||||
u"65 thousand");
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_INTEGER_FIELD, 0, 2},
|
||||
{UNUM_COMPACT_FIELD, 3, 11}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
}
|
||||
|
||||
{
|
||||
const char16_t* message = u"Compact field with inner space";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
u"compact-long",
|
||||
NumberFormatter::with().notation(Notation::compactLong()),
|
||||
"fil", // locale with interesting data
|
||||
6000,
|
||||
u"6 na libo");
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_INTEGER_FIELD, 0, 1},
|
||||
{UNUM_COMPACT_FIELD, 2, 9}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
}
|
||||
|
||||
{
|
||||
const char16_t* message = u"Compact field with bidi mark";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
u"compact-long",
|
||||
NumberFormatter::with().notation(Notation::compactLong()),
|
||||
"he", // locale with interesting data
|
||||
6000,
|
||||
u"\u200F6 אלף");
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_INTEGER_FIELD, 1, 2},
|
||||
{UNUM_COMPACT_FIELD, 3, 6}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
}
|
||||
|
||||
{
|
||||
const char16_t* message = u"Compact with currency fields";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
u"compact-short currency/USD",
|
||||
NumberFormatter::with().notation(Notation::compactShort()).unit(USD),
|
||||
"sr_Latn", // locale with interesting data
|
||||
65000,
|
||||
u"65 hilj. US$");
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_INTEGER_FIELD, 0, 2},
|
||||
{UNUM_COMPACT_FIELD, 3, 8},
|
||||
{UNUM_CURRENCY_FIELD, 9, 12}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
}
|
||||
|
||||
{
|
||||
const char16_t* message = u"Compact with measure unit fields";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
u"compact-long measure-unit/length-meter unit-width-full-name",
|
||||
NumberFormatter::with().notation(Notation::compactLong())
|
||||
.unit(METER)
|
||||
.unitWidth(UNUM_UNIT_WIDTH_FULL_NAME),
|
||||
Locale::getUS(),
|
||||
65000,
|
||||
u"65 thousand meters");
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_INTEGER_FIELD, 0, 2},
|
||||
{UNUM_COMPACT_FIELD, 3, 11},
|
||||
{UNUM_MEASURE_UNIT_FIELD, 12, 18}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
}
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::toFormat() {
|
||||
|
|
|
@ -26,7 +26,7 @@ void PatternModifierTest::testBasic() {
|
|||
ParsedPatternInfo patternInfo;
|
||||
PatternParser::parseToPatternInfo(u"a0b", patternInfo, status);
|
||||
assertSuccess("Spot 1", status);
|
||||
mod.setPatternInfo(&patternInfo);
|
||||
mod.setPatternInfo(&patternInfo, UNUM_FIELD_COUNT);
|
||||
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
|
||||
DecimalFormatSymbols symbols(Locale::getEnglish(), status);
|
||||
CurrencySymbols currencySymbols({u"USD", status}, "en", status);
|
||||
|
@ -58,7 +58,7 @@ void PatternModifierTest::testBasic() {
|
|||
ParsedPatternInfo patternInfo2;
|
||||
PatternParser::parseToPatternInfo(u"a0b;c-0d", patternInfo2, status);
|
||||
assertSuccess("Spot 4", status);
|
||||
mod.setPatternInfo(&patternInfo2);
|
||||
mod.setPatternInfo(&patternInfo2, UNUM_FIELD_COUNT);
|
||||
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
|
||||
mod.setNumberProperties(1, StandardPlural::Form::COUNT);
|
||||
assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
|
||||
|
@ -88,7 +88,7 @@ void PatternModifierTest::testPatternWithNoPlaceholder() {
|
|||
ParsedPatternInfo patternInfo;
|
||||
PatternParser::parseToPatternInfo(u"abc", patternInfo, status);
|
||||
assertSuccess("Spot 1", status);
|
||||
mod.setPatternInfo(&patternInfo);
|
||||
mod.setPatternInfo(&patternInfo, UNUM_FIELD_COUNT);
|
||||
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
|
||||
DecimalFormatSymbols symbols(Locale::getEnglish(), status);
|
||||
CurrencySymbols currencySymbols({u"USD", status}, "en", status);
|
||||
|
@ -131,7 +131,7 @@ void PatternModifierTest::testMutableEqualsImmutable() {
|
|||
ParsedPatternInfo patternInfo;
|
||||
PatternParser::parseToPatternInfo("a0b;c-0d", patternInfo, status);
|
||||
assertSuccess("Spot 1", status);
|
||||
mod.setPatternInfo(&patternInfo);
|
||||
mod.setPatternInfo(&patternInfo, UNUM_FIELD_COUNT);
|
||||
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
|
||||
DecimalFormatSymbols symbols(Locale::getEnglish(), status);
|
||||
CurrencySymbols currencySymbols({u"USD", status}, "en", status);
|
||||
|
|
|
@ -309,7 +309,8 @@ public class AffixUtils {
|
|||
CharSequence affixPattern,
|
||||
NumberStringBuilder output,
|
||||
int position,
|
||||
SymbolProvider provider) {
|
||||
SymbolProvider provider,
|
||||
NumberFormat.Field field) {
|
||||
assert affixPattern != null;
|
||||
int length = 0;
|
||||
long tag = 0L;
|
||||
|
@ -324,7 +325,7 @@ public class AffixUtils {
|
|||
provider.getSymbol(typeOrCp),
|
||||
getFieldForType(typeOrCp));
|
||||
} else {
|
||||
length += output.insertCodePoint(position + length, typeOrCp, null);
|
||||
length += output.insertCodePoint(position + length, typeOrCp, field);
|
||||
}
|
||||
}
|
||||
return length;
|
||||
|
|
|
@ -38,6 +38,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
|
|||
|
||||
// Pattern details
|
||||
AffixPatternProvider patternInfo;
|
||||
Field field;
|
||||
SignDisplay signDisplay;
|
||||
boolean perMilleReplacesPercent;
|
||||
|
||||
|
@ -71,9 +72,13 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
|
|||
* Sets a reference to the parsed decimal format pattern, usually obtained from
|
||||
* {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of
|
||||
* {@link AffixPatternProvider} is accepted.
|
||||
*
|
||||
* @param field
|
||||
* Which field to use for literal characters in the pattern.
|
||||
*/
|
||||
public void setPatternInfo(AffixPatternProvider patternInfo) {
|
||||
public void setPatternInfo(AffixPatternProvider patternInfo, Field field) {
|
||||
this.patternInfo = patternInfo;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -343,13 +348,13 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
|
|||
|
||||
private int insertPrefix(NumberStringBuilder sb, int position) {
|
||||
prepareAffix(true);
|
||||
int length = AffixUtils.unescape(currentAffix, sb, position, this);
|
||||
int length = AffixUtils.unescape(currentAffix, sb, position, this, field);
|
||||
return length;
|
||||
}
|
||||
|
||||
private int insertSuffix(NumberStringBuilder sb, int position) {
|
||||
prepareAffix(false);
|
||||
int length = AffixUtils.unescape(currentAffix, sb, position, this);
|
||||
int length = AffixUtils.unescape(currentAffix, sb, position, this, field);
|
||||
return length;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.ibm.icu.impl.number.MutablePatternModifier.ImmutablePatternModifier;
|
|||
import com.ibm.icu.impl.number.PatternStringParser;
|
||||
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
|
||||
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
|
@ -96,7 +97,7 @@ public class CompactNotation extends Notation {
|
|||
}
|
||||
if (buildReference != null) {
|
||||
// Safe code path
|
||||
precomputedMods = new HashMap<String, ImmutablePatternModifier>();
|
||||
precomputedMods = new HashMap<>();
|
||||
precomputeAllModifiers(buildReference);
|
||||
} else {
|
||||
// Unsafe code path
|
||||
|
@ -106,12 +107,12 @@ public class CompactNotation extends Notation {
|
|||
|
||||
/** Used by the safe code path */
|
||||
private void precomputeAllModifiers(MutablePatternModifier buildReference) {
|
||||
Set<String> allPatterns = new HashSet<String>();
|
||||
Set<String> allPatterns = new HashSet<>();
|
||||
data.getUniquePatterns(allPatterns);
|
||||
|
||||
for (String patternString : allPatterns) {
|
||||
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
|
||||
buildReference.setPatternInfo(patternInfo);
|
||||
buildReference.setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
|
||||
precomputedMods.put(patternString, buildReference.createImmutable());
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +149,7 @@ public class CompactNotation extends Notation {
|
|||
// Overwrite the PatternInfo in the existing modMiddle.
|
||||
assert micros.modMiddle instanceof MutablePatternModifier;
|
||||
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
|
||||
((MutablePatternModifier) micros.modMiddle).setPatternInfo(patternInfo);
|
||||
((MutablePatternModifier) micros.modMiddle).setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
|
||||
}
|
||||
|
||||
// We already performed rounding. Do not perform it again.
|
||||
|
|
|
@ -322,7 +322,7 @@ class NumberFormatterImpl {
|
|||
// Middle modifier (patterns, positive/negative, currency symbols, percent)
|
||||
// The default middle modifier is weak (thus the false argument).
|
||||
MutablePatternModifier patternMod = new MutablePatternModifier(false);
|
||||
patternMod.setPatternInfo((macros.affixProvider != null) ? macros.affixProvider : patternInfo);
|
||||
patternMod.setPatternInfo((macros.affixProvider != null) ? macros.affixProvider : patternInfo, null);
|
||||
patternMod.setPatternAttributes(micros.sign, isPermille);
|
||||
if (patternMod.needsPlurals()) {
|
||||
if (rules == null) {
|
||||
|
|
|
@ -1966,6 +1966,11 @@ public abstract class NumberFormat extends UFormat {
|
|||
*/
|
||||
public static final Field MEASURE_UNIT = new Field("measure unit");
|
||||
|
||||
/**
|
||||
* @draft ICU 64
|
||||
*/
|
||||
public static final Field COMPACT = new Field("compact");
|
||||
|
||||
/**
|
||||
* Constructs a new instance of NumberFormat.Field with the given field
|
||||
* name.
|
||||
|
|
|
@ -204,14 +204,14 @@ public class AffixUtilsTest {
|
|||
String input = cas[0];
|
||||
String expected = cas[1];
|
||||
sb.clear();
|
||||
AffixUtils.unescape(input, sb, 0, provider);
|
||||
AffixUtils.unescape(input, sb, 0, provider, null);
|
||||
assertEquals("With symbol provider on <" + input + ">", expected, sb.toString());
|
||||
}
|
||||
|
||||
// Test insertion position
|
||||
sb.clear();
|
||||
sb.append("abcdefg", null);
|
||||
AffixUtils.unescape("-+%", sb, 4, provider);
|
||||
AffixUtils.unescape("-+%", sb, 4, provider, null);
|
||||
assertEquals("Symbol provider into middle", "abcd123efg", sb.toString());
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ public class AffixUtilsTest {
|
|||
|
||||
private static String unescapeWithDefaults(String input) {
|
||||
NumberStringBuilder nsb = new NumberStringBuilder();
|
||||
int length = AffixUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER);
|
||||
int length = AffixUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER, null);
|
||||
assertEquals("Return value of unescape", nsb.length(), length);
|
||||
return nsb.toString();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public class MutablePatternModifierTest {
|
|||
@Test
|
||||
public void basic() {
|
||||
MutablePatternModifier mod = new MutablePatternModifier(false);
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b"));
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b"), null);
|
||||
mod.setPatternAttributes(SignDisplay.AUTO, false);
|
||||
mod.setSymbols(DecimalFormatSymbols.getInstance(ULocale.ENGLISH),
|
||||
Currency.getInstance("USD"),
|
||||
|
@ -51,7 +51,7 @@ public class MutablePatternModifierTest {
|
|||
assertEquals("a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"));
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"), null);
|
||||
mod.setPatternAttributes(SignDisplay.AUTO, false);
|
||||
mod.setNumberProperties(1, null);
|
||||
assertEquals("a", getPrefix(mod));
|
||||
|
@ -76,7 +76,7 @@ public class MutablePatternModifierTest {
|
|||
@Test
|
||||
public void mutableEqualsImmutable() {
|
||||
MutablePatternModifier mod = new MutablePatternModifier(false);
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"));
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"), null);
|
||||
mod.setPatternAttributes(SignDisplay.AUTO, false);
|
||||
mod.setSymbols(DecimalFormatSymbols.getInstance(ULocale.ENGLISH), null, UnitWidth.SHORT, null);
|
||||
DecimalQuantity fq = new DecimalQuantity_DualStorageBCD(1);
|
||||
|
@ -106,7 +106,7 @@ public class MutablePatternModifierTest {
|
|||
@Test
|
||||
public void patternWithNoPlaceholder() {
|
||||
MutablePatternModifier mod = new MutablePatternModifier(false);
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("abc"));
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("abc"), null);
|
||||
mod.setPatternAttributes(SignDisplay.AUTO, false);
|
||||
mod.setSymbols(DecimalFormatSymbols.getInstance(ULocale.ENGLISH),
|
||||
Currency.getInstance("USD"),
|
||||
|
|
|
@ -2317,6 +2317,124 @@ public class NumberFormatterApiTest {
|
|||
result,
|
||||
expectedFieldPositions);
|
||||
}
|
||||
|
||||
{
|
||||
String message = "Compact field basic";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
"compact-short",
|
||||
NumberFormatter.with().notation(Notation.compactShort()),
|
||||
ULocale.US,
|
||||
65000,
|
||||
"65K");
|
||||
Object[][] expectedFieldPositions = new Object[][] {
|
||||
// field, begin index, end index
|
||||
{NumberFormat.Field.INTEGER, 0, 2},
|
||||
{NumberFormat.Field.COMPACT, 2, 3}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions);
|
||||
}
|
||||
|
||||
{
|
||||
String message = "Compact field with spaces";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
"compact-long",
|
||||
NumberFormatter.with().notation(Notation.compactLong()),
|
||||
ULocale.US,
|
||||
65000,
|
||||
"65 thousand");
|
||||
Object[][] expectedFieldPositions = new Object[][] {
|
||||
// field, begin index, end index
|
||||
{NumberFormat.Field.INTEGER, 0, 2},
|
||||
{NumberFormat.Field.COMPACT, 3, 11}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions);
|
||||
}
|
||||
|
||||
{
|
||||
String message = "Compact field with inner space";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
"compact-long",
|
||||
NumberFormatter.with().notation(Notation.compactLong()),
|
||||
new ULocale("fil"), // locale with interesting data
|
||||
6000,
|
||||
"6 na libo");
|
||||
Object[][] expectedFieldPositions = new Object[][] {
|
||||
// field, begin index, end index
|
||||
{NumberFormat.Field.INTEGER, 0, 1},
|
||||
{NumberFormat.Field.COMPACT, 2, 9}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions);
|
||||
}
|
||||
|
||||
{
|
||||
String message = "Compact field with bidi mark";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
"compact-long",
|
||||
NumberFormatter.with().notation(Notation.compactLong()),
|
||||
new ULocale("he"), // locale with interesting data
|
||||
6000,
|
||||
"\u200F6 אלף");
|
||||
Object[][] expectedFieldPositions = new Object[][] {
|
||||
// field, begin index, end index
|
||||
{NumberFormat.Field.INTEGER, 1, 2},
|
||||
{NumberFormat.Field.COMPACT, 3, 6}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions);
|
||||
}
|
||||
|
||||
{
|
||||
String message = "Compact with currency fields";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
"compact-short currency/USD",
|
||||
NumberFormatter.with().notation(Notation.compactShort()).unit(USD),
|
||||
new ULocale("sr_Latn"), // locale with interesting data
|
||||
65000,
|
||||
"65 hilj. US$");
|
||||
Object[][] expectedFieldPositions = new Object[][] {
|
||||
// field, begin index, end index
|
||||
{NumberFormat.Field.INTEGER, 0, 2},
|
||||
{NumberFormat.Field.COMPACT, 3, 8},
|
||||
{NumberFormat.Field.CURRENCY, 9, 12}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions);
|
||||
}
|
||||
|
||||
{
|
||||
String message = "Compact with measure unit fields";
|
||||
FormattedNumber result = assertFormatSingle(
|
||||
message,
|
||||
"compact-long measure-unit/length-meter unit-width-full-name",
|
||||
NumberFormatter.with().notation(Notation.compactLong())
|
||||
.unit(MeasureUnit.METER)
|
||||
.unitWidth(UnitWidth.FULL_NAME),
|
||||
ULocale.US,
|
||||
65000,
|
||||
"65 thousand meters");
|
||||
Object[][] expectedFieldPositions = new Object[][] {
|
||||
// field, begin index, end index
|
||||
{NumberFormat.Field.INTEGER, 0, 2},
|
||||
{NumberFormat.Field.COMPACT, 3, 11},
|
||||
{NumberFormat.Field.MEASURE_UNIT, 12, 18}};
|
||||
assertFieldPositions(
|
||||
message,
|
||||
result,
|
||||
expectedFieldPositions);
|
||||
}
|
||||
}
|
||||
|
||||
/** Handler for serialization compatibility test suite. */
|
||||
|
|
Loading…
Add table
Reference in a new issue