ICU-20709 Adding fourth signum type. Converting Java to use enum.
This commit is contained in:
parent
e94657e614
commit
369e67221c
@ -319,10 +319,14 @@ bool DecimalQuantity::isNegative() const {
|
||||
}
|
||||
|
||||
Signum DecimalQuantity::signum() const {
|
||||
if (isNegative()) {
|
||||
bool isZero = (isZeroish() && !isInfinite());
|
||||
bool isNeg = isNegative();
|
||||
if (isZero && isNeg) {
|
||||
return SIGNUM_NEG_ZERO;
|
||||
} else if (isZero) {
|
||||
return SIGNUM_POS_ZERO;
|
||||
} else if (isNeg) {
|
||||
return SIGNUM_NEG;
|
||||
} else if (isZeroish() && !isInfinite()) {
|
||||
return SIGNUM_ZERO;
|
||||
} else {
|
||||
return SIGNUM_POS;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormat
|
||||
if (U_FAILURE(status)) { return; }
|
||||
SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_ZERO, plural});
|
||||
fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_POS_ZERO, plural});
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +325,7 @@ void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFor
|
||||
if (U_FAILURE(status)) { return; }
|
||||
SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_ZERO, plural});
|
||||
fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_POS_ZERO, plural});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,12 +319,12 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
|
||||
|
||||
private:
|
||||
// NOTE: mods is zero-initialized (to nullptr)
|
||||
const Modifier *mods[3 * StandardPlural::COUNT] = {};
|
||||
const Modifier *mods[4 * StandardPlural::COUNT] = {};
|
||||
|
||||
inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) {
|
||||
U_ASSERT(signum >= -1 && signum <= 1);
|
||||
U_ASSERT(signum >= 0 && signum <= 3);
|
||||
U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT);
|
||||
return static_cast<int32_t>(plural) * 3 + (signum + 1);
|
||||
return static_cast<int32_t>(plural) * 4 + signum;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -81,8 +81,10 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren
|
||||
for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) {
|
||||
setNumberProperties(SIGNUM_POS, plural);
|
||||
pm->adoptModifier(SIGNUM_POS, plural, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_ZERO, plural);
|
||||
pm->adoptModifier(SIGNUM_ZERO, plural, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG_ZERO, plural);
|
||||
pm->adoptModifier(SIGNUM_NEG_ZERO, plural, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_POS_ZERO, plural);
|
||||
pm->adoptModifier(SIGNUM_POS_ZERO, plural, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG, plural);
|
||||
pm->adoptModifier(SIGNUM_NEG, plural, createConstantModifier(status));
|
||||
}
|
||||
@ -95,8 +97,10 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren
|
||||
// Faster path when plural keyword is not needed.
|
||||
setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_POS, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_ZERO, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_NEG_ZERO, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_POS_ZERO, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_NEG, createConstantModifier(status));
|
||||
if (U_FAILURE(status)) {
|
||||
@ -263,7 +267,12 @@ int32_t MutablePatternModifier::insertSuffix(FormattedStringBuilder& sb, int pos
|
||||
/** 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, fPerMilleReplacesPercent, currentAffix);
|
||||
*fPatternInfo,
|
||||
isPrefix,
|
||||
PatternStringUtils::resolveSignDisplay(fSignDisplay, fSignum),
|
||||
fPlural,
|
||||
fPerMilleReplacesPercent,
|
||||
currentAffix);
|
||||
}
|
||||
|
||||
UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const {
|
||||
|
@ -1000,23 +1000,19 @@ PatternStringUtils::convertLocalized(const UnicodeString& input, const DecimalFo
|
||||
}
|
||||
|
||||
void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
|
||||
Signum signum, UNumberSignDisplay signDisplay,
|
||||
PatternSignType patternSignType,
|
||||
StandardPlural::Form plural,
|
||||
bool perMilleReplacesPercent, UnicodeString& output) {
|
||||
|
||||
// Should the output render '+' where '-' would normally appear in the pattern?
|
||||
bool plusReplacesMinusSign = signum != -1 && (
|
||||
signDisplay == UNUM_SIGN_ALWAYS || signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS || (
|
||||
signum == 1 && (
|
||||
signDisplay == UNUM_SIGN_EXCEPT_ZERO ||
|
||||
signDisplay == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO))) &&
|
||||
patternInfo.positiveHasPlusSign() == false;
|
||||
bool plusReplacesMinusSign = (patternSignType == PATTERN_SIGN_TYPE_POS_SIGN)
|
||||
&& !patternInfo.positiveHasPlusSign();
|
||||
|
||||
// Should we use the affix from the negative subpattern? (If not, we will use the positive
|
||||
// subpattern.)
|
||||
// TODO: Deal with signum
|
||||
bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() && (
|
||||
signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
|
||||
// Should we use the affix from the negative subpattern?
|
||||
// (If not, we will use the positive subpattern.)
|
||||
bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern()
|
||||
&& (patternSignType == PATTERN_SIGN_TYPE_NEG
|
||||
|| (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
|
||||
|
||||
// Resolve the flags for the affix pattern.
|
||||
int flags = 0;
|
||||
@ -1035,8 +1031,8 @@ void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider&
|
||||
bool prependSign;
|
||||
if (!isPrefix || useNegativeAffixPattern) {
|
||||
prependSign = false;
|
||||
} else if (signum == -1) {
|
||||
prependSign = signDisplay != UNUM_SIGN_NEVER;
|
||||
} else if (patternSignType == PATTERN_SIGN_TYPE_NEG) {
|
||||
prependSign = true;
|
||||
} else {
|
||||
prependSign = plusReplacesMinusSign;
|
||||
}
|
||||
@ -1065,4 +1061,54 @@ void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider&
|
||||
}
|
||||
}
|
||||
|
||||
PatternSignType PatternStringUtils::resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum) {
|
||||
switch (signDisplay) {
|
||||
case UNUM_SIGN_AUTO:
|
||||
case UNUM_SIGN_ACCOUNTING:
|
||||
switch (signum) {
|
||||
case SIGNUM_NEG:
|
||||
case SIGNUM_NEG_ZERO:
|
||||
return PATTERN_SIGN_TYPE_NEG;
|
||||
case SIGNUM_POS_ZERO:
|
||||
case SIGNUM_POS:
|
||||
return PATTERN_SIGN_TYPE_POS;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNUM_SIGN_ALWAYS:
|
||||
case UNUM_SIGN_ACCOUNTING_ALWAYS:
|
||||
switch (signum) {
|
||||
case SIGNUM_NEG:
|
||||
case SIGNUM_NEG_ZERO:
|
||||
return PATTERN_SIGN_TYPE_NEG;
|
||||
case SIGNUM_POS_ZERO:
|
||||
case SIGNUM_POS:
|
||||
return PATTERN_SIGN_TYPE_POS_SIGN;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNUM_SIGN_EXCEPT_ZERO:
|
||||
case UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO:
|
||||
switch (signum) {
|
||||
case SIGNUM_NEG:
|
||||
return PATTERN_SIGN_TYPE_NEG;
|
||||
case SIGNUM_NEG_ZERO:
|
||||
case SIGNUM_POS_ZERO:
|
||||
return PATTERN_SIGN_TYPE_POS;
|
||||
case SIGNUM_POS:
|
||||
return PATTERN_SIGN_TYPE_POS_SIGN;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNUM_SIGN_NEVER:
|
||||
return PATTERN_SIGN_TYPE_POS;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
UPRV_UNREACHABLE;
|
||||
return PATTERN_SIGN_TYPE_POS;
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -22,6 +22,18 @@ namespace impl {
|
||||
// Forward declaration
|
||||
class PatternParser;
|
||||
|
||||
// Note: the order of fields in this enum matters for parsing.
|
||||
enum PatternSignType {
|
||||
/** Render using normal positive subpattern rules */
|
||||
PATTERN_SIGN_TYPE_POS,
|
||||
/** Render using rules to force the display of a plus sign */
|
||||
PATTERN_SIGN_TYPE_POS_SIGN,
|
||||
/** Render using negative subpattern rules */
|
||||
PATTERN_SIGN_TYPE_NEG,
|
||||
/** Count for looping over the possibilities */
|
||||
PATTERN_SIGN_TYPE_COUNT
|
||||
};
|
||||
|
||||
// Exported as U_I18N_API because it is a public member field of exported ParsedSubpatternInfo
|
||||
struct U_I18N_API Endpoints {
|
||||
int32_t start = 0;
|
||||
@ -295,10 +307,12 @@ class U_I18N_API PatternStringUtils {
|
||||
* substitution, and plural forms for CurrencyPluralInfo.
|
||||
*/
|
||||
static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
|
||||
Signum signum, UNumberSignDisplay signDisplay,
|
||||
PatternSignType patternSignType,
|
||||
StandardPlural::Form plural, bool perMilleReplacesPercent,
|
||||
UnicodeString& output);
|
||||
|
||||
static PatternSignType resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum);
|
||||
|
||||
private:
|
||||
/** @return The number of chars inserted. */
|
||||
static int escapePaddingString(UnicodeString input, UnicodeString& output, int startIndex,
|
||||
|
@ -92,9 +92,10 @@ enum CompactType {
|
||||
};
|
||||
|
||||
enum Signum {
|
||||
SIGNUM_NEG = -1,
|
||||
SIGNUM_ZERO = 0,
|
||||
SIGNUM_POS = 1
|
||||
SIGNUM_NEG = 0,
|
||||
SIGNUM_NEG_ZERO = 1,
|
||||
SIGNUM_POS_ZERO = 2,
|
||||
SIGNUM_POS = 3
|
||||
};
|
||||
|
||||
|
||||
|
@ -271,8 +271,6 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt
|
||||
// Use initial capacity of 6, the highest possible number of AffixMatchers.
|
||||
UnicodeString sb;
|
||||
bool includeUnpaired = 0 != (parseFlags & PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES);
|
||||
UNumberSignDisplay signDisplay = (0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) ? UNUM_SIGN_ALWAYS
|
||||
: UNUM_SIGN_AUTO;
|
||||
|
||||
int32_t numAffixMatchers = 0;
|
||||
int32_t numAffixPatternMatchers = 0;
|
||||
@ -281,13 +279,23 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt
|
||||
AffixPatternMatcher* posSuffix = nullptr;
|
||||
|
||||
// Pre-process the affix strings to resolve LDML rules like sign display.
|
||||
for (int8_t signumInt = 1; signumInt >= -1; signumInt--) {
|
||||
auto signum = static_cast<Signum>(signumInt);
|
||||
for (int8_t typeInt = 0; typeInt < PATTERN_SIGN_TYPE_COUNT; typeInt++) {
|
||||
auto type = static_cast<PatternSignType>(typeInt);
|
||||
|
||||
// Skip affixes in some cases
|
||||
if (type == PATTERN_SIGN_TYPE_POS
|
||||
&& 0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
|
||||
continue;
|
||||
}
|
||||
if (type == PATTERN_SIGN_TYPE_POS_SIGN
|
||||
&& 0 == (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Generate Prefix
|
||||
bool hasPrefix = false;
|
||||
PatternStringUtils::patternInfoToStringBuilder(
|
||||
patternInfo, true, signum, signDisplay, StandardPlural::OTHER, false, sb);
|
||||
patternInfo, true, type, StandardPlural::OTHER, false, sb);
|
||||
fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
|
||||
sb, *fTokenWarehouse, parseFlags, &hasPrefix, status);
|
||||
AffixPatternMatcher* prefix = hasPrefix ? &fAffixPatternMatchers[numAffixPatternMatchers++]
|
||||
@ -296,13 +304,13 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt
|
||||
// Generate Suffix
|
||||
bool hasSuffix = false;
|
||||
PatternStringUtils::patternInfoToStringBuilder(
|
||||
patternInfo, false, signum, signDisplay, StandardPlural::OTHER, false, sb);
|
||||
patternInfo, false, type, StandardPlural::OTHER, false, sb);
|
||||
fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
|
||||
sb, *fTokenWarehouse, parseFlags, &hasSuffix, status);
|
||||
AffixPatternMatcher* suffix = hasSuffix ? &fAffixPatternMatchers[numAffixPatternMatchers++]
|
||||
: nullptr;
|
||||
|
||||
if (signum == 1) {
|
||||
if (type == PATTERN_SIGN_TYPE_POS) {
|
||||
posPrefix = prefix;
|
||||
posSuffix = suffix;
|
||||
} else if (equals(prefix, posPrefix) && equals(suffix, posSuffix)) {
|
||||
@ -311,17 +319,17 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt
|
||||
}
|
||||
|
||||
// Flags for setting in the ParsedNumber; the token matchers may add more.
|
||||
int flags = (signum == -1) ? FLAG_NEGATIVE : 0;
|
||||
int flags = (type == PATTERN_SIGN_TYPE_NEG) ? FLAG_NEGATIVE : 0;
|
||||
|
||||
// Note: it is indeed possible for posPrefix and posSuffix to both be null.
|
||||
// We still need to add that matcher for strict mode to work.
|
||||
fAffixMatchers[numAffixMatchers++] = {prefix, suffix, flags};
|
||||
if (includeUnpaired && prefix != nullptr && suffix != nullptr) {
|
||||
// The following if statements are designed to prevent adding two identical matchers.
|
||||
if (signum == 1 || !equals(prefix, posPrefix)) {
|
||||
if (type == PATTERN_SIGN_TYPE_POS || !equals(prefix, posPrefix)) {
|
||||
fAffixMatchers[numAffixMatchers++] = {prefix, nullptr, flags};
|
||||
}
|
||||
if (signum == 1 || !equals(suffix, posSuffix)) {
|
||||
if (type == PATTERN_SIGN_TYPE_POS || !equals(suffix, posSuffix)) {
|
||||
fAffixMatchers[numAffixMatchers++] = {nullptr, suffix, flags};
|
||||
}
|
||||
}
|
||||
|
@ -2114,7 +2114,7 @@ void NumberFormatterApiTest::signCoverage() {
|
||||
{ UNUM_SIGN_AUTO, { u"-∞", u"-1", u"-0", u"0", u"1", u"∞", u"NaN", u"-NaN" } },
|
||||
{ UNUM_SIGN_ALWAYS, { u"-∞", u"-1", u"-0", u"+0", u"+1", u"+∞", u"+NaN", u"-NaN" } },
|
||||
{ UNUM_SIGN_NEVER, { u"∞", u"1", u"0", u"0", u"1", u"∞", u"NaN", u"NaN" } },
|
||||
{ UNUM_SIGN_EXCEPT_ZERO, { u"-∞", u"-1", u"-0", u"0", u"+1", u"+∞", u"NaN", u"-NaN" } },
|
||||
{ UNUM_SIGN_EXCEPT_ZERO, { u"-∞", u"-1", u"0", u"0", u"+1", u"+∞", u"NaN", u"NaN" } },
|
||||
};
|
||||
double negNaN = std::copysign(uprv_getNaN(), -0.0);
|
||||
const double inputs[] = {
|
||||
|
@ -41,7 +41,10 @@ void PatternModifierTest::testBasic() {
|
||||
mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false);
|
||||
assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
|
||||
mod.setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT);
|
||||
mod.setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
|
||||
assertEquals("Pattern a0b", u"-a", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
|
||||
mod.setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
|
||||
assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
|
||||
mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false);
|
||||
@ -66,7 +69,10 @@ void PatternModifierTest::testBasic() {
|
||||
mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false);
|
||||
assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
|
||||
mod.setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT);
|
||||
mod.setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
|
||||
assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
|
||||
mod.setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
|
||||
assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
|
||||
mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false);
|
||||
@ -76,9 +82,8 @@ void PatternModifierTest::testBasic() {
|
||||
assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
|
||||
mod.setPatternAttributes(UNUM_SIGN_NEVER, false);
|
||||
// TODO: What should this behavior be?
|
||||
assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
|
||||
assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
|
||||
assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status));
|
||||
assertSuccess("Spot 5", status);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
package com.ibm.icu.impl.number;
|
||||
|
||||
import com.ibm.icu.impl.StandardPlural;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
|
||||
/**
|
||||
* This implementation of ModifierStore adopts references to Modifiers.
|
||||
@ -11,7 +12,8 @@ import com.ibm.icu.impl.StandardPlural;
|
||||
*/
|
||||
public class AdoptingModifierStore implements ModifierStore {
|
||||
private final Modifier positive;
|
||||
private final Modifier zero;
|
||||
private final Modifier posZero;
|
||||
private final Modifier negZero;
|
||||
private final Modifier negative;
|
||||
final Modifier[] mods;
|
||||
boolean frozen;
|
||||
@ -22,9 +24,10 @@ public class AdoptingModifierStore implements ModifierStore {
|
||||
* <p>
|
||||
* If this constructor is used, a plural form CANNOT be passed to {@link #getModifier}.
|
||||
*/
|
||||
public AdoptingModifierStore(Modifier positive, Modifier zero, Modifier negative) {
|
||||
public AdoptingModifierStore(Modifier positive, Modifier posZero, Modifier negZero, Modifier negative) {
|
||||
this.positive = positive;
|
||||
this.zero = zero;
|
||||
this.posZero = posZero;
|
||||
this.negZero = negZero;
|
||||
this.negative = negative;
|
||||
this.mods = null;
|
||||
this.frozen = true;
|
||||
@ -39,13 +42,14 @@ public class AdoptingModifierStore implements ModifierStore {
|
||||
*/
|
||||
public AdoptingModifierStore() {
|
||||
this.positive = null;
|
||||
this.zero = null;
|
||||
this.posZero = null;
|
||||
this.negZero = null;
|
||||
this.negative = null;
|
||||
this.mods = new Modifier[3 * StandardPlural.COUNT];
|
||||
this.mods = new Modifier[4 * StandardPlural.COUNT];
|
||||
this.frozen = false;
|
||||
}
|
||||
|
||||
public void setModifier(int signum, StandardPlural plural, Modifier mod) {
|
||||
public void setModifier(Signum signum, StandardPlural plural, Modifier mod) {
|
||||
assert !frozen;
|
||||
mods[getModIndex(signum, plural)] = mod;
|
||||
}
|
||||
@ -54,21 +58,34 @@ public class AdoptingModifierStore implements ModifierStore {
|
||||
frozen = true;
|
||||
}
|
||||
|
||||
public Modifier getModifierWithoutPlural(int signum) {
|
||||
public Modifier getModifierWithoutPlural(Signum signum) {
|
||||
assert frozen;
|
||||
assert mods == null;
|
||||
return signum == 0 ? zero : signum < 0 ? negative : positive;
|
||||
assert signum != null;
|
||||
switch (signum) {
|
||||
case POS:
|
||||
return positive;
|
||||
case POS_ZERO:
|
||||
return posZero;
|
||||
case NEG_ZERO:
|
||||
return negZero;
|
||||
case NEG:
|
||||
return negative;
|
||||
default:
|
||||
throw new AssertionError("Unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
public Modifier getModifier(int signum, StandardPlural plural) {
|
||||
@Override
|
||||
public Modifier getModifier(Signum signum, StandardPlural plural) {
|
||||
assert frozen;
|
||||
assert positive == null;
|
||||
return mods[getModIndex(signum, plural)];
|
||||
}
|
||||
|
||||
private static int getModIndex(int signum, StandardPlural plural) {
|
||||
assert signum >= -1 && signum <= 1;
|
||||
private static int getModIndex(Signum signum, StandardPlural plural) {
|
||||
assert signum != null;
|
||||
assert plural != null;
|
||||
return plural.ordinal() * 3 + (signum + 1);
|
||||
return plural.ordinal() * 4 + signum.ordinal();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import java.math.MathContext;
|
||||
import java.text.FieldPosition;
|
||||
|
||||
import com.ibm.icu.impl.StandardPlural;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
import com.ibm.icu.text.UFieldPosition;
|
||||
|
||||
@ -130,8 +131,8 @@ public interface DecimalQuantity extends PluralRules.IFixedDecimal {
|
||||
/** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
|
||||
public boolean isNegative();
|
||||
|
||||
/** @return -1 if the value is negative; 1 if positive; or 0 if zero. */
|
||||
public int signum();
|
||||
/** @return The appropriate value from the Signum enum. */
|
||||
public Signum signum();
|
||||
|
||||
/** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
|
||||
@Override
|
||||
|
@ -9,6 +9,7 @@ import java.text.FieldPosition;
|
||||
|
||||
import com.ibm.icu.impl.StandardPlural;
|
||||
import com.ibm.icu.impl.Utility;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
import com.ibm.icu.text.PluralRules.Operand;
|
||||
import com.ibm.icu.text.UFieldPosition;
|
||||
@ -303,8 +304,18 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int signum() {
|
||||
return isNegative() ? -1 : (isZeroish() && !isInfinite()) ? 0 : 1;
|
||||
public Signum signum() {
|
||||
boolean isZero = (isZeroish() && !isInfinite());
|
||||
boolean isNeg = isNegative();
|
||||
if (isZero && isNeg) {
|
||||
return Signum.NEG_ZERO;
|
||||
} else if (isZero) {
|
||||
return Signum.POS_ZERO;
|
||||
} else if (isNeg) {
|
||||
return Signum.NEG;
|
||||
} else {
|
||||
return Signum.POS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -12,6 +12,7 @@ import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.SimpleFormatterImpl;
|
||||
import com.ibm.icu.impl.StandardPlural;
|
||||
import com.ibm.icu.impl.UResource;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
import com.ibm.icu.number.NumberFormatter.UnitWidth;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
@ -262,7 +263,7 @@ public class LongNameHandler implements MicroPropsGenerator, ModifierStore {
|
||||
String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 0, 1);
|
||||
Modifier.Parameters parameters = new Modifier.Parameters();
|
||||
parameters.obj = this;
|
||||
parameters.signum = 0;
|
||||
parameters.signum = null;// Signum ignored
|
||||
parameters.plural = plural;
|
||||
modifiers.put(plural, new SimpleModifier(compiled, field, false, parameters));
|
||||
}
|
||||
@ -281,7 +282,7 @@ public class LongNameHandler implements MicroPropsGenerator, ModifierStore {
|
||||
.compileToStringMinMaxArguments(compoundFormat, sb, 0, 1);
|
||||
Modifier.Parameters parameters = new Modifier.Parameters();
|
||||
parameters.obj = this;
|
||||
parameters.signum = 0;
|
||||
parameters.signum = null; // Signum ignored
|
||||
parameters.plural = plural;
|
||||
modifiers.put(plural, new SimpleModifier(compoundCompiled, field, false, parameters));
|
||||
}
|
||||
@ -296,7 +297,8 @@ public class LongNameHandler implements MicroPropsGenerator, ModifierStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier(int signum, StandardPlural plural) {
|
||||
public Modifier getModifier(Signum signum, StandardPlural plural) {
|
||||
// Signum ignored
|
||||
return modifiers.get(plural);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,13 @@ import com.ibm.icu.impl.StandardPlural;
|
||||
*/
|
||||
public interface Modifier {
|
||||
|
||||
static enum Signum {
|
||||
NEG,
|
||||
NEG_ZERO,
|
||||
POS_ZERO,
|
||||
POS
|
||||
};
|
||||
|
||||
/**
|
||||
* Apply this Modifier to the string builder.
|
||||
*
|
||||
@ -65,7 +72,7 @@ public interface Modifier {
|
||||
*/
|
||||
public static class Parameters {
|
||||
public ModifierStore obj;
|
||||
public int signum;
|
||||
public Signum signum;
|
||||
public StandardPlural plural;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
package com.ibm.icu.impl.number;
|
||||
|
||||
import com.ibm.icu.impl.StandardPlural;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
|
||||
/**
|
||||
* This is *not* a modifier; rather, it is an object that can return modifiers
|
||||
@ -14,5 +15,5 @@ public interface ModifierStore {
|
||||
/**
|
||||
* Returns a Modifier with the given parameters (best-effort).
|
||||
*/
|
||||
Modifier getModifier(int signum, StandardPlural plural);
|
||||
Modifier getModifier(Signum signum, StandardPlural plural);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
|
||||
PluralRules rules;
|
||||
|
||||
// Number details
|
||||
int signum;
|
||||
Signum signum;
|
||||
StandardPlural plural;
|
||||
|
||||
// QuantityChain details
|
||||
@ -129,7 +129,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
|
||||
* The plural form of the number, required only if the pattern contains the triple
|
||||
* currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
|
||||
*/
|
||||
public void setNumberProperties(int signum, StandardPlural plural) {
|
||||
public void setNumberProperties(Signum signum, StandardPlural plural) {
|
||||
assert (plural != null) == needsPlurals();
|
||||
this.signum = signum;
|
||||
this.plural = plural;
|
||||
@ -174,24 +174,28 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
|
||||
// Slower path when we require the plural keyword.
|
||||
AdoptingModifierStore pm = new AdoptingModifierStore();
|
||||
for (StandardPlural plural : StandardPlural.VALUES) {
|
||||
setNumberProperties(1, plural);
|
||||
pm.setModifier(1, plural, createConstantModifier(a, b));
|
||||
setNumberProperties(0, plural);
|
||||
pm.setModifier(0, plural, createConstantModifier(a, b));
|
||||
setNumberProperties(-1, plural);
|
||||
pm.setModifier(-1, plural, createConstantModifier(a, b));
|
||||
setNumberProperties(Signum.POS, plural);
|
||||
pm.setModifier(Signum.POS, plural, createConstantModifier(a, b));
|
||||
setNumberProperties(Signum.POS_ZERO, plural);
|
||||
pm.setModifier(Signum.POS_ZERO, plural, createConstantModifier(a, b));
|
||||
setNumberProperties(Signum.NEG_ZERO, plural);
|
||||
pm.setModifier(Signum.NEG_ZERO, plural, createConstantModifier(a, b));
|
||||
setNumberProperties(Signum.NEG, plural);
|
||||
pm.setModifier(Signum.NEG, plural, createConstantModifier(a, b));
|
||||
}
|
||||
pm.freeze();
|
||||
return new ImmutablePatternModifier(pm, rules, parent);
|
||||
} else {
|
||||
// Faster path when plural keyword is not needed.
|
||||
setNumberProperties(1, null);
|
||||
setNumberProperties(Signum.POS, null);
|
||||
Modifier positive = createConstantModifier(a, b);
|
||||
setNumberProperties(0, null);
|
||||
Modifier zero = createConstantModifier(a, b);
|
||||
setNumberProperties(-1, null);
|
||||
setNumberProperties(Signum.POS_ZERO, null);
|
||||
Modifier posZero = createConstantModifier(a, b);
|
||||
setNumberProperties(Signum.NEG_ZERO, null);
|
||||
Modifier negZero = createConstantModifier(a, b);
|
||||
setNumberProperties(Signum.NEG, null);
|
||||
Modifier negative = createConstantModifier(a, b);
|
||||
AdoptingModifierStore pm = new AdoptingModifierStore(positive, zero, negative);
|
||||
AdoptingModifierStore pm = new AdoptingModifierStore(positive, posZero, negZero, negative);
|
||||
return new ImmutablePatternModifier(pm, null, parent);
|
||||
}
|
||||
}
|
||||
@ -367,8 +371,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
|
||||
}
|
||||
PatternStringUtils.patternInfoToStringBuilder(patternInfo,
|
||||
isPrefix,
|
||||
signum,
|
||||
signDisplay,
|
||||
PatternStringUtils.resolveSignDisplay(signDisplay, signum),
|
||||
plural,
|
||||
perMilleReplacesPercent,
|
||||
currentAffix);
|
||||
|
@ -5,6 +5,7 @@ package com.ibm.icu.impl.number;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.ibm.icu.impl.StandardPlural;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
import com.ibm.icu.impl.number.Padder.PadPosition;
|
||||
import com.ibm.icu.number.NumberFormatter.SignDisplay;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
@ -14,6 +15,18 @@ import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
*/
|
||||
public class PatternStringUtils {
|
||||
|
||||
// Note: the order of fields in this enum matters for parsing.
|
||||
public static enum PatternSignType {
|
||||
// Render using normal positive subpattern rules
|
||||
POS,
|
||||
// Render using rules to force the display of a plus sign
|
||||
POS_SIGN,
|
||||
// Render using negative subpattern rules
|
||||
NEG;
|
||||
|
||||
public static final PatternSignType[] VALUES = PatternSignType.values();
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine whether a given roundingIncrement should be ignored for formatting
|
||||
* based on the current maxFrac value (maximum fraction digits). For example a
|
||||
@ -23,7 +36,7 @@ public class PatternStringUtils {
|
||||
* it should not be ignored if maxFrac is 2 or more (but a roundingIncrement of
|
||||
* 0.005 is treated like 0.001 for significance).
|
||||
*
|
||||
* This test is needed for both NumberPropertyMapper.oldToNew and
|
||||
* This test is needed for both NumberPropertyMapper.oldToNew and
|
||||
* PatternStringUtils.propertiesToPatternString, but NumberPropertyMapper
|
||||
* is package-private so we have it here.
|
||||
*
|
||||
@ -416,25 +429,19 @@ public class PatternStringUtils {
|
||||
public static void patternInfoToStringBuilder(
|
||||
AffixPatternProvider patternInfo,
|
||||
boolean isPrefix,
|
||||
int signum,
|
||||
SignDisplay signDisplay,
|
||||
PatternSignType patternSignType,
|
||||
StandardPlural plural,
|
||||
boolean perMilleReplacesPercent,
|
||||
StringBuilder output) {
|
||||
|
||||
// Should the output render '+' where '-' would normally appear in the pattern?
|
||||
boolean plusReplacesMinusSign = signum != -1
|
||||
&& (signDisplay == SignDisplay.ALWAYS
|
||||
|| signDisplay == SignDisplay.ACCOUNTING_ALWAYS
|
||||
|| (signum == 1
|
||||
&& (signDisplay == SignDisplay.EXCEPT_ZERO
|
||||
|| signDisplay == SignDisplay.ACCOUNTING_EXCEPT_ZERO)))
|
||||
&& patternInfo.positiveHasPlusSign() == false;
|
||||
boolean plusReplacesMinusSign = (patternSignType == PatternSignType.POS_SIGN)
|
||||
&& !patternInfo.positiveHasPlusSign();
|
||||
|
||||
// Should we use the affix from the negative subpattern? (If not, we will use the positive
|
||||
// subpattern.)
|
||||
// Should we use the affix from the negative subpattern?
|
||||
// (If not, we will use the positive subpattern.)
|
||||
boolean useNegativeAffixPattern = patternInfo.hasNegativeSubpattern()
|
||||
&& (signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
|
||||
&& (patternSignType == PatternSignType.NEG
|
||||
|| (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
|
||||
|
||||
// Resolve the flags for the affix pattern.
|
||||
int flags = 0;
|
||||
@ -453,8 +460,8 @@ public class PatternStringUtils {
|
||||
boolean prependSign;
|
||||
if (!isPrefix || useNegativeAffixPattern) {
|
||||
prependSign = false;
|
||||
} else if (signum == -1) {
|
||||
prependSign = signDisplay != SignDisplay.NEVER;
|
||||
} else if (patternSignType == PatternSignType.NEG) {
|
||||
prependSign = true;
|
||||
} else {
|
||||
prependSign = plusReplacesMinusSign;
|
||||
}
|
||||
@ -483,4 +490,53 @@ public class PatternStringUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static PatternSignType resolveSignDisplay(SignDisplay signDisplay, Signum signum) {
|
||||
switch (signDisplay) {
|
||||
case AUTO:
|
||||
case ACCOUNTING:
|
||||
switch (signum) {
|
||||
case NEG:
|
||||
case NEG_ZERO:
|
||||
return PatternSignType.NEG;
|
||||
case POS_ZERO:
|
||||
case POS:
|
||||
return PatternSignType.POS;
|
||||
}
|
||||
break;
|
||||
|
||||
case ALWAYS:
|
||||
case ACCOUNTING_ALWAYS:
|
||||
switch (signum) {
|
||||
case NEG:
|
||||
case NEG_ZERO:
|
||||
return PatternSignType.NEG;
|
||||
case POS_ZERO:
|
||||
case POS:
|
||||
return PatternSignType.POS_SIGN;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCEPT_ZERO:
|
||||
case ACCOUNTING_EXCEPT_ZERO:
|
||||
switch (signum) {
|
||||
case NEG:
|
||||
return PatternSignType.NEG;
|
||||
case NEG_ZERO:
|
||||
case POS_ZERO:
|
||||
return PatternSignType.POS;
|
||||
case POS:
|
||||
return PatternSignType.POS_SIGN;
|
||||
}
|
||||
break;
|
||||
|
||||
case NEVER:
|
||||
return PatternSignType.POS;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new AssertionError("Unreachable");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import com.ibm.icu.impl.StringSegment;
|
||||
import com.ibm.icu.impl.number.AffixPatternProvider;
|
||||
import com.ibm.icu.impl.number.AffixUtils;
|
||||
import com.ibm.icu.impl.number.PatternStringUtils;
|
||||
import com.ibm.icu.number.NumberFormatter.SignDisplay;
|
||||
import com.ibm.icu.impl.number.PatternStringUtils.PatternSignType;
|
||||
|
||||
/**
|
||||
* @author sffc
|
||||
@ -90,20 +90,27 @@ public class AffixMatcher implements NumberParseMatcher {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ArrayList<AffixMatcher> matchers = new ArrayList<>(6);
|
||||
boolean includeUnpaired = 0 != (parseFlags & ParsingUtils.PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES);
|
||||
SignDisplay signDisplay = (0 != (parseFlags & ParsingUtils.PARSE_FLAG_PLUS_SIGN_ALLOWED))
|
||||
? SignDisplay.ALWAYS
|
||||
: SignDisplay.AUTO;
|
||||
|
||||
AffixPatternMatcher posPrefix = null;
|
||||
AffixPatternMatcher posSuffix = null;
|
||||
|
||||
// Pre-process the affix strings to resolve LDML rules like sign display.
|
||||
for (int signum = 1; signum >= -1; signum--) {
|
||||
for (PatternSignType type : PatternSignType.VALUES) {
|
||||
|
||||
// Skip affixes in some cases
|
||||
if (type == PatternSignType.POS
|
||||
&& 0 != (parseFlags & ParsingUtils.PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
|
||||
continue;
|
||||
}
|
||||
if (type == PatternSignType.POS_SIGN
|
||||
&& 0 == (parseFlags & ParsingUtils.PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Generate Prefix
|
||||
PatternStringUtils.patternInfoToStringBuilder(patternInfo,
|
||||
true,
|
||||
signum,
|
||||
signDisplay,
|
||||
type,
|
||||
StandardPlural.OTHER,
|
||||
false,
|
||||
sb);
|
||||
@ -113,15 +120,14 @@ public class AffixMatcher implements NumberParseMatcher {
|
||||
// Generate Suffix
|
||||
PatternStringUtils.patternInfoToStringBuilder(patternInfo,
|
||||
false,
|
||||
signum,
|
||||
signDisplay,
|
||||
type,
|
||||
StandardPlural.OTHER,
|
||||
false,
|
||||
sb);
|
||||
AffixPatternMatcher suffix = AffixPatternMatcher
|
||||
.fromAffixPattern(sb.toString(), factory, parseFlags);
|
||||
|
||||
if (signum == 1) {
|
||||
if (type == PatternSignType.POS) {
|
||||
posPrefix = prefix;
|
||||
posSuffix = suffix;
|
||||
} else if (Objects.equals(prefix, posPrefix) && Objects.equals(suffix, posSuffix)) {
|
||||
@ -130,17 +136,17 @@ public class AffixMatcher implements NumberParseMatcher {
|
||||
}
|
||||
|
||||
// Flags for setting in the ParsedNumber; the token matchers may add more.
|
||||
int flags = (signum == -1) ? ParsedNumber.FLAG_NEGATIVE : 0;
|
||||
int flags = (type == PatternSignType.NEG) ? ParsedNumber.FLAG_NEGATIVE : 0;
|
||||
|
||||
// Note: it is indeed possible for posPrefix and posSuffix to both be null.
|
||||
// We still need to add that matcher for strict mode to work.
|
||||
matchers.add(getInstance(prefix, suffix, flags));
|
||||
if (includeUnpaired && prefix != null && suffix != null) {
|
||||
// The following if statements are designed to prevent adding two identical matchers.
|
||||
if (signum == 1 || !Objects.equals(prefix, posPrefix)) {
|
||||
if (type == PatternSignType.POS || !Objects.equals(prefix, posPrefix)) {
|
||||
matchers.add(getInstance(prefix, null, flags));
|
||||
}
|
||||
if (signum == 1 || !Objects.equals(suffix, posSuffix)) {
|
||||
if (type == PatternSignType.POS || !Objects.equals(suffix, posSuffix)) {
|
||||
matchers.add(getInstance(null, suffix, flags));
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import java.text.FieldPosition;
|
||||
|
||||
import com.ibm.icu.impl.StandardPlural;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
import com.ibm.icu.text.PluralRules.Operand;
|
||||
import com.ibm.icu.text.UFieldPosition;
|
||||
@ -517,8 +518,18 @@ public class DecimalQuantity_SimpleStorage implements DecimalQuantity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int signum() {
|
||||
return isNegative() ? -1 : isZeroish() ? 0 : 1;
|
||||
public Signum signum() {
|
||||
boolean isZero = (isZeroish() && !isInfinite());
|
||||
boolean isNeg = isNegative();
|
||||
if (isZero && isNeg) {
|
||||
return Signum.NEG_ZERO;
|
||||
} else if (isZero) {
|
||||
return Signum.POS_ZERO;
|
||||
} else if (isNeg) {
|
||||
return Signum.NEG;
|
||||
} else {
|
||||
return Signum.POS;
|
||||
}
|
||||
}
|
||||
|
||||
private void setNegative(boolean isNegative) {
|
||||
|
@ -12,6 +12,7 @@ import com.ibm.icu.impl.FormattedStringBuilder;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
|
||||
import com.ibm.icu.impl.number.MicroProps;
|
||||
import com.ibm.icu.impl.number.Modifier.Signum;
|
||||
import com.ibm.icu.impl.number.MutablePatternModifier;
|
||||
import com.ibm.icu.impl.number.PatternStringParser;
|
||||
import com.ibm.icu.number.NumberFormatter.SignDisplay;
|
||||
@ -32,19 +33,22 @@ public class MutablePatternModifierTest {
|
||||
UnitWidth.SHORT,
|
||||
null);
|
||||
|
||||
mod.setNumberProperties(1, null);
|
||||
mod.setNumberProperties(Signum.POS, null);
|
||||
assertEquals("a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setPatternAttributes(SignDisplay.ALWAYS, false);
|
||||
assertEquals("+a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setNumberProperties(0, null);
|
||||
mod.setNumberProperties(Signum.POS_ZERO, null);
|
||||
assertEquals("+a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setNumberProperties(Signum.NEG_ZERO, null);
|
||||
assertEquals("-a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setPatternAttributes(SignDisplay.EXCEPT_ZERO, false);
|
||||
assertEquals("a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setNumberProperties(-1, null);
|
||||
mod.setNumberProperties(Signum.NEG, null);
|
||||
assertEquals("-a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setPatternAttributes(SignDisplay.NEVER, false);
|
||||
@ -53,24 +57,27 @@ public class MutablePatternModifierTest {
|
||||
|
||||
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"), null);
|
||||
mod.setPatternAttributes(SignDisplay.AUTO, false);
|
||||
mod.setNumberProperties(1, null);
|
||||
mod.setNumberProperties(Signum.POS, null);
|
||||
assertEquals("a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setPatternAttributes(SignDisplay.ALWAYS, false);
|
||||
assertEquals("c+", getPrefix(mod));
|
||||
assertEquals("d", getSuffix(mod));
|
||||
mod.setNumberProperties(0, null);
|
||||
mod.setNumberProperties(Signum.POS_ZERO, null);
|
||||
assertEquals("c+", getPrefix(mod));
|
||||
assertEquals("d", getSuffix(mod));
|
||||
mod.setNumberProperties(Signum.NEG_ZERO, null);
|
||||
assertEquals("c-", getPrefix(mod));
|
||||
assertEquals("d", getSuffix(mod));
|
||||
mod.setPatternAttributes(SignDisplay.EXCEPT_ZERO, false);
|
||||
assertEquals("a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
mod.setNumberProperties(-1, null);
|
||||
mod.setNumberProperties(Signum.NEG, null);
|
||||
assertEquals("c-", getPrefix(mod));
|
||||
assertEquals("d", getSuffix(mod));
|
||||
mod.setPatternAttributes(SignDisplay.NEVER, false);
|
||||
assertEquals("c-", getPrefix(mod)); // TODO: What should this behavior be?
|
||||
assertEquals("d", getSuffix(mod));
|
||||
assertEquals("a", getPrefix(mod));
|
||||
assertEquals("b", getSuffix(mod));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -112,7 +119,7 @@ public class MutablePatternModifierTest {
|
||||
Currency.getInstance("USD"),
|
||||
UnitWidth.SHORT,
|
||||
null);
|
||||
mod.setNumberProperties(1, null);
|
||||
mod.setNumberProperties(Signum.POS_ZERO, null);
|
||||
|
||||
// Unsafe Code Path
|
||||
FormattedStringBuilder nsb = new FormattedStringBuilder();
|
||||
|
@ -2036,7 +2036,7 @@ public class NumberFormatterApiTest {
|
||||
{ {SignDisplay.AUTO}, { "-∞", "-1", "-0", "0", "1", "∞", "NaN", "-NaN" } },
|
||||
{ {SignDisplay.ALWAYS}, { "-∞", "-1", "-0", "+0", "+1", "+∞", "+NaN", "-NaN" } },
|
||||
{ {SignDisplay.NEVER}, { "∞", "1", "0", "0", "1", "∞", "NaN", "NaN" } },
|
||||
{ {SignDisplay.EXCEPT_ZERO}, { "-∞", "-1", "-0", "0", "+1", "+∞", "NaN", "-NaN" } },
|
||||
{ {SignDisplay.EXCEPT_ZERO}, { "-∞", "-1", "0", "0", "+1", "+∞", "NaN", "NaN" } },
|
||||
};
|
||||
double negNaN = Math.copySign(Double.NaN, -0.0);
|
||||
double inputs[] = new double[] {
|
||||
|
Loading…
Reference in New Issue
Block a user