ICU-13574 Merging trunk to branch

X-SVN-Rev: 40867
This commit is contained in:
Shane Carr 2018-02-08 06:07:18 +00:00
commit 9337205a54
15 changed files with 213 additions and 81 deletions

View file

@ -539,6 +539,7 @@ typedef enum UErrorCode {
U_DEFAULT_KEYWORD_MISSING, /**< Missing DEFAULT rule in plural rules */
U_DECIMAL_NUMBER_SYNTAX_ERROR, /**< Decimal number syntax error */
U_FORMAT_INEXACT_ERROR, /**< Cannot format a number exactly and rounding mode is ROUND_UNNECESSARY @stable ICU 4.8 */
U_NUMBER_ARG_OUTOFBOUNDS_ERROR, /**< The argument to a NumberFormatter helper method was out of bounds; the bounds are usually 0 to 999. @draft ICU 61 */
#ifndef U_HIDE_DEPRECATED_API
/**
* One more than the highest normal formatting API error code.

View file

@ -125,7 +125,8 @@ _uFmtErrorName[U_FMT_PARSE_ERROR_LIMIT - U_FMT_PARSE_ERROR_START] = {
"U_UNDEFINED_KEYWORD",
"U_DEFAULT_KEYWORD_MISSING",
"U_DECIMAL_NUMBER_SYNTAX_ERROR",
"U_FORMAT_INEXACT_ERROR"
"U_FORMAT_INEXACT_ERROR",
"U_NUMBER_ARG_OUTOFBOUNDS_ERROR"
};
static const char * const

View file

@ -13,25 +13,28 @@ using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;
IntegerWidth::IntegerWidth(int8_t minInt, int8_t maxInt) {
IntegerWidth::IntegerWidth(digits_t minInt, digits_t maxInt) {
fUnion.minMaxInt.fMinInt = minInt;
fUnion.minMaxInt.fMaxInt = maxInt;
}
IntegerWidth IntegerWidth::zeroFillTo(int32_t minInt) {
if (minInt >= 0 && minInt <= kMaxIntFracSig) {
return {static_cast<int8_t>(minInt), -1};
return {static_cast<digits_t>(minInt), -1};
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
IntegerWidth IntegerWidth::truncateAt(int32_t maxInt) {
if (fHasError) { return *this; } // No-op on error
if (maxInt >= 0 && maxInt <= kMaxIntFracSig) {
return {fUnion.minMaxInt.fMinInt, static_cast<int8_t>(maxInt)};
digits_t minInt = fUnion.minMaxInt.fMinInt;
if (maxInt >= 0 && maxInt <= kMaxIntFracSig && minInt <= maxInt) {
return {minInt, static_cast<digits_t>(maxInt)};
} else if (maxInt == -1) {
return {minInt, -1};
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}

View file

@ -54,13 +54,13 @@ Notation Notation::simple() {
ScientificNotation
ScientificNotation::withMinExponentDigits(int32_t minExponentDigits) const {
if (minExponentDigits >= 0 && minExponentDigits < kMaxIntFracSig) {
if (minExponentDigits >= 1 && minExponentDigits <= kMaxIntFracSig) {
ScientificSettings settings = fUnion.scientific;
settings.fMinExponentDigits = (int8_t) minExponentDigits;
settings.fMinExponentDigits = static_cast<digits_t>(minExponentDigits);
NotationUnion union_ = {settings};
return {NTN_SCIENTIFIC, union_};
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}

View file

@ -43,7 +43,7 @@ Padder Padder::codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosit
if (targetWidth >= 0) {
return {cp, targetWidth, position};
} else {
return {U_NUMBER_PADDING_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}

View file

@ -58,7 +58,7 @@ FractionRounder Rounder::fixedFraction(int32_t minMaxFractionPlaces) {
if (minMaxFractionPlaces >= 0 && minMaxFractionPlaces <= kMaxIntFracSig) {
return constructFraction(minMaxFractionPlaces, minMaxFractionPlaces);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@ -66,7 +66,7 @@ FractionRounder Rounder::minFraction(int32_t minFractionPlaces) {
if (minFractionPlaces >= 0 && minFractionPlaces <= kMaxIntFracSig) {
return constructFraction(minFractionPlaces, -1);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@ -74,7 +74,7 @@ FractionRounder Rounder::maxFraction(int32_t maxFractionPlaces) {
if (maxFractionPlaces >= 0 && maxFractionPlaces <= kMaxIntFracSig) {
return constructFraction(0, maxFractionPlaces);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@ -83,40 +83,40 @@ FractionRounder Rounder::minMaxFraction(int32_t minFractionPlaces, int32_t maxFr
minFractionPlaces <= maxFractionPlaces) {
return constructFraction(minFractionPlaces, maxFractionPlaces);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::fixedDigits(int32_t minMaxSignificantDigits) {
if (minMaxSignificantDigits >= 0 && minMaxSignificantDigits <= kMaxIntFracSig) {
if (minMaxSignificantDigits >= 1 && minMaxSignificantDigits <= kMaxIntFracSig) {
return constructSignificant(minMaxSignificantDigits, minMaxSignificantDigits);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::minDigits(int32_t minSignificantDigits) {
if (minSignificantDigits >= 0 && minSignificantDigits <= kMaxIntFracSig) {
if (minSignificantDigits >= 1 && minSignificantDigits <= kMaxIntFracSig) {
return constructSignificant(minSignificantDigits, -1);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::maxDigits(int32_t maxSignificantDigits) {
if (maxSignificantDigits >= 0 && maxSignificantDigits <= kMaxIntFracSig) {
return constructSignificant(0, maxSignificantDigits);
if (maxSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig) {
return constructSignificant(1, maxSignificantDigits);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::minMaxDigits(int32_t minSignificantDigits, int32_t maxSignificantDigits) {
if (minSignificantDigits >= 0 && maxSignificantDigits <= kMaxIntFracSig &&
if (minSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig &&
minSignificantDigits <= maxSignificantDigits) {
return constructSignificant(minSignificantDigits, maxSignificantDigits);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@ -124,7 +124,7 @@ IncrementRounder Rounder::increment(double roundingIncrement) {
if (roundingIncrement > 0.0) {
return constructIncrement(roundingIncrement, 0);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@ -139,19 +139,19 @@ Rounder Rounder::withMode(RoundingMode roundingMode) const {
Rounder FractionRounder::withMinDigits(int32_t minSignificantDigits) const {
if (fType == RND_ERROR) { return *this; } // no-op in error state
if (minSignificantDigits >= 0 && minSignificantDigits <= kMaxIntFracSig) {
if (minSignificantDigits >= 1 && minSignificantDigits <= kMaxIntFracSig) {
return constructFractionSignificant(*this, minSignificantDigits, -1);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder FractionRounder::withMaxDigits(int32_t maxSignificantDigits) const {
if (fType == RND_ERROR) { return *this; } // no-op in error state
if (maxSignificantDigits >= 0 && maxSignificantDigits <= kMaxIntFracSig) {
if (maxSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig) {
return constructFractionSignificant(*this, -1, maxSignificantDigits);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@ -185,14 +185,14 @@ Rounder IncrementRounder::withMinFraction(int32_t minFrac) const {
if (minFrac >= 0 && minFrac <= kMaxIntFracSig) {
return constructIncrement(fUnion.increment.fIncrement, minFrac);
} else {
return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
FractionRounder Rounder::constructFraction(int32_t minFrac, int32_t maxFrac) {
FractionSignificantSettings settings;
settings.fMinFrac = static_cast<int8_t> (minFrac);
settings.fMaxFrac = static_cast<int8_t> (maxFrac);
settings.fMinFrac = static_cast<digits_t>(minFrac);
settings.fMaxFrac = static_cast<digits_t>(maxFrac);
settings.fMinSig = -1;
settings.fMaxSig = -1;
RounderUnion union_;
@ -204,8 +204,8 @@ Rounder Rounder::constructSignificant(int32_t minSig, int32_t maxSig) {
FractionSignificantSettings settings;
settings.fMinFrac = -1;
settings.fMaxFrac = -1;
settings.fMinSig = static_cast<int8_t>(minSig);
settings.fMaxSig = static_cast<int8_t>(maxSig);
settings.fMinSig = static_cast<digits_t>(minSig);
settings.fMaxSig = static_cast<digits_t>(maxSig);
RounderUnion union_;
union_.fracSig = settings;
return {RND_SIGNIFICANT, union_, kDefaultMode};
@ -214,8 +214,8 @@ Rounder Rounder::constructSignificant(int32_t minSig, int32_t maxSig) {
Rounder
Rounder::constructFractionSignificant(const FractionRounder &base, int32_t minSig, int32_t maxSig) {
FractionSignificantSettings settings = base.fUnion.fracSig;
settings.fMinSig = static_cast<int8_t>(minSig);
settings.fMaxSig = static_cast<int8_t>(maxSig);
settings.fMinSig = static_cast<digits_t>(minSig);
settings.fMaxSig = static_cast<digits_t>(maxSig);
RounderUnion union_;
union_.fracSig = settings;
return {RND_FRACTION_SIGNIFICANT, union_, kDefaultMode};
@ -224,7 +224,7 @@ Rounder::constructFractionSignificant(const FractionRounder &base, int32_t minSi
IncrementRounder Rounder::constructIncrement(double increment, int32_t minFrac) {
IncrementSettings settings;
settings.fIncrement = increment;
settings.fMinFrac = minFrac;
settings.fMinFrac = static_cast<digits_t>(minFrac);
RounderUnion union_;
union_.increment = settings;
return {RND_INCREMENT, union_, kDefaultMode};

View file

@ -31,7 +31,7 @@ typedef UNumberFormatPadPosition PadPosition;
typedef UNumberCompactStyle CompactStyle;
// ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG
static constexpr int32_t kMaxIntFracSig = 100;
static constexpr int32_t kMaxIntFracSig = 999;
// ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE
static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN;
@ -42,10 +42,6 @@ static constexpr char16_t kFallbackPaddingString[] = u" ";
// ICU4J Equivalent: NumberFormatterImpl.DEFAULT_CURRENCY
static constexpr char16_t kDefaultCurrency[] = u"XXX";
// FIXME: New error codes:
static constexpr UErrorCode U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR = U_ILLEGAL_ARGUMENT_ERROR;
static constexpr UErrorCode U_NUMBER_PADDING_WIDTH_OUTOFBOUNDS_ERROR = U_ILLEGAL_ARGUMENT_ERROR;
// Forward declarations:
class Modifier;

View file

@ -394,6 +394,21 @@ class IntegerWidth;
namespace impl {
/**
* Datatype for minimum/maximum fraction digits. Must be able to hold kMaxIntFracSig.
*
* @internal
*/
typedef int16_t digits_t;
/**
* Use a default threshold of 3. This means that the third time .format() is called, the data structures get built
* using the "safe" code path. The first two calls to .format() will trigger the unsafe code path.
*
* @internal
*/
static constexpr int32_t DEFAULT_THRESHOLD = 3;
// Forward declarations:
class Padder;
struct MacroProps;
@ -577,7 +592,7 @@ class U_I18N_API Notation : public UMemory {
struct ScientificSettings {
int8_t fEngineeringInterval;
bool fRequireMinInt;
int8_t fMinExponentDigits;
impl::digits_t fMinExponentDigits;
UNumberSignDisplay fExponentSignDisplay;
} scientific;
@ -892,14 +907,14 @@ class U_I18N_API Rounder : public UMemory {
union RounderUnion {
struct FractionSignificantSettings {
// For RND_FRACTION, RND_SIGNIFICANT, and RND_FRACTION_SIGNIFICANT
int8_t fMinFrac;
int8_t fMaxFrac;
int8_t fMinSig;
int8_t fMaxSig;
impl::digits_t fMinFrac;
impl::digits_t fMaxFrac;
impl::digits_t fMinSig;
impl::digits_t fMaxSig;
} fracSig;
struct IncrementSettings {
double fIncrement;
int32_t fMinFrac;
impl::digits_t fMinFrac;
} increment; // For RND_INCREMENT
UCurrencyUsage currencyUsage; // For RND_CURRENCY
UErrorCode errorCode; // For RND_ERROR
@ -1153,7 +1168,8 @@ class U_I18N_API IntegerWidth : public UMemory {
* For example, with maxInt=3, the number 1234 will get printed as "234".
*
* @param maxInt
* The maximum number of places before the decimal separator.
* The maximum number of places before the decimal separator. maxInt == -1 means no
* truncation.
* @return An IntegerWidth for passing to the NumberFormatter integerWidth() setter.
* @draft ICU 60
* @see NumberFormatter
@ -1163,14 +1179,14 @@ class U_I18N_API IntegerWidth : public UMemory {
private:
union {
struct {
int8_t fMinInt;
int8_t fMaxInt;
impl::digits_t fMinInt;
impl::digits_t fMaxInt;
} minMaxInt;
UErrorCode errorCode;
} fUnion;
bool fHasError = false;
IntegerWidth(int8_t minInt, int8_t maxInt);
IntegerWidth(impl::digits_t minInt, impl::digits_t maxInt);
IntegerWidth(UErrorCode errorCode) { // NOLINT
fUnion.errorCode = errorCode;
@ -1205,14 +1221,6 @@ class U_I18N_API IntegerWidth : public UMemory {
namespace impl {
/**
* Use a default threshold of 3. This means that the third time .format() is called, the data structures get built
* using the "safe" code path. The first two calls to .format() will trigger the unsafe code path.
*
* @internal
*/
static constexpr int32_t DEFAULT_THRESHOLD = 3;
/** @internal */
class U_I18N_API SymbolsWrapper : public UMemory {
public:

View file

@ -2030,6 +2030,25 @@ UBool IntlTest::assertEquals(const char* message,
return TRUE;
}
UBool IntlTest::assertEquals(const char* message,
UErrorCode expected,
UErrorCode actual) {
if (expected != actual) {
errln((UnicodeString)"FAIL: " + message + "; got " +
u_errorName(actual) +
"; expected " + u_errorName(expected));
return FALSE;
}
#ifdef VERBOSE_ASSERTIONS
else {
logln((UnicodeString)"Ok: " + message + "; got " + u_errorName(actual));
}
#endif
return TRUE;
}
#if !UCONFIG_NO_FORMATTING
UBool IntlTest::assertEquals(const char* message,
const Formattable& expected,
@ -2105,6 +2124,16 @@ UBool IntlTest::assertEquals(const UnicodeString& message,
int64_t actual) {
return assertEquals(extractToAssertBuf(message), expected, actual);
}
UBool IntlTest::assertEquals(const UnicodeString& message,
double expected,
double actual) {
return assertEquals(extractToAssertBuf(message), expected, actual);
}
UBool IntlTest::assertEquals(const UnicodeString& message,
UErrorCode expected,
UErrorCode actual) {
return assertEquals(extractToAssertBuf(message), expected, actual);
}
#if !UCONFIG_NO_FORMATTING
UBool IntlTest::assertEquals(const UnicodeString& message,

View file

@ -289,13 +289,12 @@ public:
UBool assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError=FALSE, const char *file=NULL, int line=0);
UBool assertEquals(const char* message, const UnicodeString& expected,
const UnicodeString& actual, UBool possibleDataError=FALSE);
UBool assertEquals(const char* message, const char* expected,
const char* actual);
UBool assertEquals(const char* message, UBool expected,
UBool actual);
UBool assertEquals(const char* message, const char* expected, const char* actual);
UBool assertEquals(const char* message, UBool expected, UBool actual);
UBool assertEquals(const char* message, int32_t expected, int32_t actual);
UBool assertEquals(const char* message, int64_t expected, int64_t actual);
UBool assertEquals(const char* message, double expected, double actual);
UBool assertEquals(const char* message, UErrorCode expected, UErrorCode actual);
#if !UCONFIG_NO_FORMATTING
UBool assertEquals(const char* message, const Formattable& expected,
const Formattable& actual, UBool possibleDataError=FALSE);
@ -307,11 +306,12 @@ public:
UBool assertSuccess(const UnicodeString& message, UErrorCode ec);
UBool assertEquals(const UnicodeString& message, const UnicodeString& expected,
const UnicodeString& actual, UBool possibleDataError=FALSE);
UBool assertEquals(const UnicodeString& message, const char* expected,
const char* actual);
UBool assertEquals(const UnicodeString& message, const char* expected, const char* actual);
UBool assertEquals(const UnicodeString& message, UBool expected, UBool actual);
UBool assertEquals(const UnicodeString& message, int32_t expected, int32_t actual);
UBool assertEquals(const UnicodeString& message, int64_t expected, int64_t actual);
UBool assertEquals(const UnicodeString& message, double expected, double actual);
UBool assertEquals(const UnicodeString& message, UErrorCode expected, UErrorCode actual);
virtual void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ); // overide !

View file

@ -67,6 +67,7 @@ class NumberFormatterApiTest : public IntlTest {
void locale();
void formatTypes();
void errors();
void validRanges();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);

View file

@ -76,6 +76,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
TESTCASE_AUTO(locale);
TESTCASE_AUTO(formatTypes);
TESTCASE_AUTO(errors);
TESTCASE_AUTO(validRanges);
TESTCASE_AUTO_END;
}
@ -1748,27 +1749,83 @@ void NumberFormatterApiTest::errors() {
UErrorCode status2 = U_ZERO_ERROR;
FormattedNumber fn = lnf.formatInt(1, status1);
assertEquals(
"Should fail with U_ILLEGAL_ARGUMENT_ERROR since rounder is not legal",
U_ILLEGAL_ARGUMENT_ERROR,
status1);
"Should fail since rounder is not legal",
(UBool) TRUE,
(UBool) U_FAILURE(status1));
FieldPosition fp;
fn.populateFieldPosition(fp, status2);
assertEquals(
"Should fail with U_ILLEGAL_ARGUMENT_ERROR on terminal method",
U_ILLEGAL_ARGUMENT_ERROR,
status2);
"Should fail on terminal method",
(UBool) TRUE,
(UBool) U_FAILURE(status2));
}
{
UErrorCode status = U_ZERO_ERROR;
lnf.copyErrorTo(status);
assertEquals(
"Should fail with U_ILLEGAL_ARGUMENT_ERROR since rounder is not legal",
U_ILLEGAL_ARGUMENT_ERROR,
status);
"Should fail since rounder is not legal",
(UBool) TRUE,
(UBool) U_FAILURE(status));
}
}
void NumberFormatterApiTest::validRanges() {
#define EXPECTED_MAX_INT_FRAC_SIG 999
#define VALID_RANGE_ASSERT(status, method, lowerBound, argument) { \
UErrorCode expectedStatus = ((lowerBound <= argument) && (argument <= EXPECTED_MAX_INT_FRAC_SIG)) \
? U_ZERO_ERROR \
: U_NUMBER_ARG_OUTOFBOUNDS_ERROR; \
assertEquals( \
UnicodeString(u"Incorrect status for " #method " on input ") \
+ Int64ToUnicodeString(argument), \
expectedStatus, \
status); \
}
#define VALID_RANGE_ONEARG(setting, method, lowerBound) { \
for (int32_t argument = -2; argument <= EXPECTED_MAX_INT_FRAC_SIG + 2; argument++) { \
UErrorCode status = U_ZERO_ERROR; \
NumberFormatter::with().setting(method(argument)).copyErrorTo(status); \
VALID_RANGE_ASSERT(status, method, lowerBound, argument); \
} \
}
#define VALID_RANGE_TWOARGS(setting, method, lowerBound) { \
for (int32_t argument = -2; argument <= EXPECTED_MAX_INT_FRAC_SIG + 2; argument++) { \
UErrorCode status = U_ZERO_ERROR; \
/* Pass EXPECTED_MAX_INT_FRAC_SIG as the second argument so arg1 <= arg2 in expected cases */ \
NumberFormatter::with().setting(method(argument, EXPECTED_MAX_INT_FRAC_SIG)).copyErrorTo(status); \
VALID_RANGE_ASSERT(status, method, lowerBound, argument); \
status = U_ZERO_ERROR; \
/* Pass lowerBound as the first argument so arg1 <= arg2 in expected cases */ \
NumberFormatter::with().setting(method(lowerBound, argument)).copyErrorTo(status); \
VALID_RANGE_ASSERT(status, method, lowerBound, argument); \
/* Check that first argument must be less than or equal to second argument */ \
NumberFormatter::with().setting(method(argument, argument - 1)).copyErrorTo(status); \
assertEquals("Incorrect status for " #method " on max < min input", \
U_NUMBER_ARG_OUTOFBOUNDS_ERROR, \
status); \
} \
}
VALID_RANGE_ONEARG(rounding, Rounder::fixedFraction, 0);
VALID_RANGE_ONEARG(rounding, Rounder::minFraction, 0);
VALID_RANGE_ONEARG(rounding, Rounder::maxFraction, 0);
VALID_RANGE_TWOARGS(rounding, Rounder::minMaxFraction, 0);
VALID_RANGE_ONEARG(rounding, Rounder::fixedDigits, 1);
VALID_RANGE_ONEARG(rounding, Rounder::minDigits, 1);
VALID_RANGE_ONEARG(rounding, Rounder::maxDigits, 1);
VALID_RANGE_TWOARGS(rounding, Rounder::minMaxDigits, 1);
VALID_RANGE_ONEARG(rounding, Rounder::fixedFraction(1).withMinDigits, 1);
VALID_RANGE_ONEARG(rounding, Rounder::fixedFraction(1).withMaxDigits, 1);
VALID_RANGE_ONEARG(notation, Notation::scientific().withMinExponentDigits, 1);
VALID_RANGE_ONEARG(integerWidth, IntegerWidth::zeroFillTo, 0);
VALID_RANGE_ONEARG(integerWidth, IntegerWidth::zeroFillTo(0).truncateAt, -1);
}
void NumberFormatterApiTest::assertFormatDescending(const UnicodeString &message,
const UnlocalizedNumberFormatter &f,

View file

@ -22,7 +22,7 @@ public class RoundingUtils {
* The maximum number of fraction places, integer numerals, or significant digits. TODO: This does
* not feel like the best home for this value.
*/
public static final int MAX_INT_FRAC_SIG = 100;
public static final int MAX_INT_FRAC_SIG = 999;
/**
* Converts a rounding mode and metadata about the quantity being rounded to a boolean determining

View file

@ -311,6 +311,36 @@ public class IntlTestDecimalFormatSymbols extends TestFmwk
errln("ERROR: Char digits should be Latin digits");
}
// Check on copy
DecimalFormatSymbols copy = (DecimalFormatSymbols) symbols.clone();
if (!Arrays.equals(copy.getDigitStrings(), osmanyaDigitStrings)) {
errln("ERROR: Osmanya digits (supplementary) should be set");
}
if (Character.codePointAt(osmanyaDigitStrings[0], 0) != copy.getCodePointZero()) {
errln("ERROR: Code point zero be Osmanya code point zero");
}
if (defZero != copy.getZeroDigit()) {
errln("ERROR: Zero digit should be 0");
}
if (!Arrays.equals(copy.getDigits(), defDigits)) {
errln("ERROR: Char digits should be Latin digits");
}
// Check on resource bundle
DecimalFormatSymbols fromData = DecimalFormatSymbols.getInstance(new ULocale("en@numbers=osma"));
if (!Arrays.equals(fromData.getDigitStrings(), osmanyaDigitStrings)) {
errln("ERROR: Osmanya digits (supplementary) should be set");
}
if (Character.codePointAt(osmanyaDigitStrings[0], 0) != fromData.getCodePointZero()) {
errln("ERROR: Code point zero be Osmanya code point zero");
}
if (defZero != fromData.getZeroDigit()) {
errln("ERROR: Zero digit should be 0");
}
if (!Arrays.equals(fromData.getDigits(), defDigits)) {
errln("ERROR: Char digits should be Latin digits");
}
symbols.setDigitStrings(differentDigitStrings);
if (!Arrays.equals(symbols.getDigitStrings(), differentDigitStrings)) {
errln("ERROR: Different digits should be set");

View file

@ -1897,12 +1897,12 @@ public class NumberFormatterApiTest {
Rounder.class.getDeclaredMethod("minMaxFraction", Integer.TYPE, Integer.TYPE),
Rounder.class.getDeclaredMethod("minMaxDigits", Integer.TYPE, Integer.TYPE), };
final int EXPECTED_MAX_INT_FRAC_SIG = 100;
final String expectedSubstring0 = "between 0 and 100 (inclusive)";
final String expectedSubstring1 = "between 1 and 100 (inclusive)";
final String expectedSubstringN1 = "between -1 and 100 (inclusive)";
final int EXPECTED_MAX_INT_FRAC_SIG = 999;
final String expectedSubstring0 = "between 0 and 999 (inclusive)";
final String expectedSubstring1 = "between 1 and 999 (inclusive)";
final String expectedSubstringN1 = "between -1 and 999 (inclusive)";
// We require that the upper bounds all be 100 inclusive.
// We require that the upper bounds all be 999 inclusive.
// The lower bound may be either -1, 0, or 1.
Set<String> methodsWithLowerBound1 = new HashSet();
methodsWithLowerBound1.add("fixedDigits");
@ -1912,6 +1912,12 @@ public class NumberFormatterApiTest {
methodsWithLowerBound1.add("withMinDigits");
methodsWithLowerBound1.add("withMaxDigits");
methodsWithLowerBound1.add("withMinExponentDigits");
// Methods with lower bound 0:
// fixedFraction
// minFraction
// maxFraction
// minMaxFraction
// zeroFillTo
Set<String> methodsWithLowerBoundN1 = new HashSet();
methodsWithLowerBoundN1.add("truncateAt");