mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-13443 Change digit width types to int16_t and change maximum setting to 999. Adds test for this behavior in ICU4C. Also adds the new error code for ICU-13577 .
X-SVN-Rev: 40866
This commit is contained in:
parent
baca9ac330
commit
ad348faca9
14 changed files with 183 additions and 81 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 !
|
||||
|
||||
|
|
|
@ -63,6 +63,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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue