ICU-813 int64 formatting support

X-SVN-Rev: 13547
This commit is contained in:
Doug Felt 2003-10-31 22:47:25 +00:00
parent 87cd8a5be1
commit e5a79dc60c
18 changed files with 506 additions and 45 deletions

View file

@ -73,7 +73,7 @@ brkiter.o brkdict.o ubrk.o dbbi.o dbbi_tbl.o \
rbbi.o rbbidata.o rbbinode.o rbbirb.o rbbiscan.o rbbisetb.o rbbistbl.o rbbitblb.o \
icuserv.o iculserv.o icunotif.o uenum.o ustrenum.o \
uidna.o usprep.o punycode.o \
cwchar.o filestrm.o umemstrm.o digitlst.o util.o parsepos.o utrace.o
cwchar.o filestrm.o umemstrm.o util.o parsepos.o utrace.o
STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))

View file

@ -1626,14 +1626,6 @@ InputPath=.\unicode\uobject.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\digitlst.cpp
# End Source File
# Begin Source File
SOURCE=.\digitlst.h
# End Source File
# Begin Source File
SOURCE=.\unicode\parseerr.h
!IF "$(CFG)" == "common - Win32 Release"

View file

@ -70,7 +70,7 @@ nultrans.o remtrans.o titletrn.o tolowtrn.o toupptrn.o anytrans.o \
name2uni.o uni2name.o unitohex.o nortrans.o quant.o transreg.o \
nfrs.o nfrule.o nfsubs.o rbnf.o esctrn.o unesctrn.o \
funcrepl.o strrepl.o tridpars.o \
ucurr.o \
ucurr.o digitlst.o \
regexcmp.o rematch.o repattrn.o regexst.o

View file

@ -565,6 +565,19 @@ ChoiceFormat::getFormats(int32_t& cnt) const
return fChoiceFormats;
}
// -------------------------------------
// Formats an int64 number, it's actually formatted as
// a double. The returned format string may differ
// from the input number because of this.
UnicodeString&
ChoiceFormat::format(int64_t number,
UnicodeString& appendTo,
FieldPosition& status) const
{
return format((double) number, appendTo, status);
}
// -------------------------------------
// Formats a long number, it's actually formatted as
// a double. The returned format string may differ

View file

@ -105,6 +105,40 @@ const int32_t DecimalFormat::kDoubleIntegerDigits = 309;
const int32_t DecimalFormat::kDoubleFractionDigits = 340;
const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
#if 0
class Test {
private:
int32_t f;
public:
// void a(int arg);
void a(int32_t arg);
void a(int64_t arg);
void a(double arg);
};
//void Test::a(int arg) { f = (int32_t)arg; }
void Test::a(int32_t arg) { f = arg; }
void Test::a(int64_t arg) { f = (int32_t)arg; }
void Test::a(double arg) { f = (int32_t)arg; }
static void test(uint64_t num) {
Test t;
int32_t zero32 = 0;
int64_t zero64 = 0;
double zeroDbl = 0;
t.a((int32_t)0);
t.a((int64_t)0);
t.a((double)0);
t.a(0);
t.a(0.0);
t.a(0.0f);
// t.a(zero32);
// t.a(zero64);
// t.a(zeroDbl);
// t.a(num);
}
#endif
/**
* These are the tags we expect to see in normal resource bundle files associated
@ -593,6 +627,16 @@ UnicodeString&
DecimalFormat::format(int32_t number,
UnicodeString& appendTo,
FieldPosition& fieldPosition) const
{
return format((int64_t)number, appendTo, fieldPosition);
}
//------------------------------------------------------------------------------
UnicodeString&
DecimalFormat::format(int64_t number,
UnicodeString& appendTo,
FieldPosition& fieldPosition) const
{
DigitList digits;
@ -610,8 +654,8 @@ DecimalFormat::format(int32_t number,
// check for this before multiplying, and if it happens we use doubles
// instead, trading off accuracy for range.
if (fRoundingIncrement != NULL
|| (fMultiplier != 0 && (number > (INT32_MAX / fMultiplier)
|| number < (INT32_MIN / fMultiplier))))
|| (fMultiplier != 0 && (number > (INT64_MAX / fMultiplier)
|| number < (INT64_MIN / fMultiplier))))
{
digits.set(((double)number) * fMultiplier,
precision(FALSE),
@ -1187,6 +1231,17 @@ DecimalFormat::parse(const UnicodeString& text,
return;
}
}
else if (digits.fitsIntoInt64(isParseIntegerOnly())) {
int64_t n = digits.getInt64();
if (n % mult == 0) {
result.setInt64(n / mult);
return;
}
else { // else handle the remainder
result.setDouble(((double)n) / mult);
return;
}
}
else {
// Handle non-integral or very large values
// Dividing by one is okay and not that costly.

View file

@ -47,9 +47,13 @@ static char gDecimal = 0;
/* Only for 32 bit numbers. Ignore the negative sign. */
static const char LONG_MIN_REP[] = "2147483648";
static const char I64_MIN_REP[] = "9223372036854775808";
static const int64_t I64_MIN_VALUE = -9223372036854775807 - 1;
enum {
LONG_MIN_REP_LENGTH = sizeof(LONG_MIN_REP) - 1 //Ignore the NULL at the end
LONG_MIN_REP_LENGTH = sizeof(LONG_MIN_REP) - 1, //Ignore the NULL at the end
I64_MIN_REP_LENGTH = sizeof(I64_MIN_REP) - 1 //Ignore the NULL at the end
};
U_NAMESPACE_BEGIN
@ -133,7 +137,7 @@ DigitList::clear()
* @return the number of digits written, not including the sign.
*/
static int32_t
formatBase10(int32_t number, char *outputStr, int32_t outputLen)
formatBase10(int64_t number, char *outputStr, int32_t outputLen)
{
char buffer[MAX_DIGITS + 1];
int32_t bufferLen;
@ -232,6 +236,49 @@ int32_t DigitList::getLong()
}
}
/**
* Make sure that fitsIntoInt64() is called before calling this function.
*/
int64_t DigitList::getInt64()
{
if (fCount == fDecimalAt) {
uint64_t value;
fDigits[fCount] = 0; // NULL terminate
// This conversion is bad on 64-bit platforms when we want to
// be able to return a 64-bit number [grhoten]
*fDecimalDigits = fIsPositive ? '+' : '-';
if (fCount < LONG_MIN_REP_LENGTH) {
return (int64_t)atol(fDecimalDigits);
}
// too big for atol, hand-roll atoi64
value = 0;
for (int i = 0; i < fCount; ++i) {
int v = fDigits[i] - kZero;
value = value * (uint64_t)10 + (uint64_t)v;
}
if (!fIsPositive) {
value = ~value;
value += 1;
}
int64_t svalue = (int64_t)value;
return svalue;
}
else {
// todo: figure out best approach
// This is 100% accurate in c++ because if we are representing
// an integral value, we suffer nothing in the conversion to
// double. If we are to support 64-bit longs later, getLong()
// must be rewritten. [LIU]
return (int64_t)getDouble();
}
}
/**
* Return true if the number represented by this object can fit into
* a long.
@ -241,9 +288,7 @@ DigitList::fitsIntoLong(UBool ignoreNegativeZero)
{
// Figure out if the result will fit in a long. We have to
// first look for nonzero digits after the decimal point;
// then check the size. If the digit count is 18 or less, then
// the value can definitely be represented as a long. If it is 19
// then it may be too large.
// then check the size.
// Trim trailing zeros after the decimal point. This does not change
// the represented value.
@ -291,14 +336,79 @@ DigitList::fitsIntoLong(UBool ignoreNegativeZero)
return !fIsPositive;
}
/**
* Return true if the number represented by this object can fit into
* a long.
*/
UBool
DigitList::fitsIntoInt64(UBool ignoreNegativeZero)
{
// Figure out if the result will fit in a long. We have to
// first look for nonzero digits after the decimal point;
// then check the size.
// Trim trailing zeros after the decimal point. This does not change
// the represented value.
while (fCount > fDecimalAt && fCount > 0 && fDigits[fCount - 1] == kZero)
--fCount;
if (fCount == 0) {
// Positive zero fits into a long, but negative zero can only
// be represented as a double. - bug 4162852
return fIsPositive || ignoreNegativeZero;
}
// initializeLONG_MIN_REP();
// If the digit list represents a double or this number is too
// big for a long.
if (fDecimalAt < fCount || fDecimalAt > I64_MIN_REP_LENGTH)
return FALSE;
// If number is small enough to fit in an int64
if (fDecimalAt < I64_MIN_REP_LENGTH)
return TRUE;
// At this point we have fDecimalAt == fCount, and fCount == INT64_MIN_REP_LENGTH.
// The number will overflow if it is larger than INT64_MAX
// or smaller than INT64_MIN.
for (int32_t i=0; i<fCount; ++i)
{
char dig = fDigits[i],
max = I64_MIN_REP[i];
if (dig > max)
return FALSE;
if (dig < max)
return TRUE;
}
// At this point the first count digits match. If fDecimalAt is less
// than count, then the remaining digits are zero, and we return true.
if (fCount < fDecimalAt)
return TRUE;
// Now we have a representation of INT64_MIN_VALUE, without the leading
// negative sign. If this represents a positive value, then it does
// not fit; otherwise it fits.
return !fIsPositive;
}
// -------------------------------------
void
DigitList::set(int32_t source, int32_t maximumDigits)
{
set((int64_t)source, maximumDigits);
}
// -------------------------------------
/**
* @param maximumDigits The maximum digits to be generated. If zero,
* there is no maximum -- generate all digits.
*/
void
DigitList::set(int32_t source, int32_t maximumDigits)
DigitList::set(int64_t source, int32_t maximumDigits)
{
fCount = fDecimalAt = formatBase10(source, fDecimalDigits, MAX_DIGITS);
@ -335,7 +445,7 @@ DigitList::set(double source, int32_t maximumDigits, UBool fixedPoint)
fIsPositive = !uprv_isNegative(source); // Allow +0 and -0
// Generate a representation of the form /[+-][0-9]+e[+-][0-9]+/
sprintf(rep, "%+1.*e", MAX_DIGITS - 1, source);
sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
fDecimalAt = 0;
rep[2] = rep[1]; // remove decimal
@ -347,7 +457,7 @@ DigitList::set(double source, int32_t maximumDigits, UBool fixedPoint)
while (*repPtr != 'e') {
*(digitPtr++) = *(repPtr++);
}
fCount = MAX_DIGITS + fDecimalAt;
fCount = MAX_DBL_DIGITS + fDecimalAt;
// Parse an exponent of the form /[eE][+-][0-9]+/
UBool negExp = (*(++repPtr) == '-');

View file

@ -28,16 +28,19 @@
#include "unicode/uobject.h"
#include <float.h>
// Decimal digits in a 32-bit int
// Decimal digits in a 64-bit int
//#define LONG_DIGITS 19
#define INT64_DIGITS 19
typedef enum EDigitListValues {
MAX_DIGITS = DBL_DIG,
MAX_DBL_DIGITS = DBL_DIG,
MAX_I64_DIGITS = INT64_DIGITS,
MAX_DIGITS = MAX_I64_DIGITS,
MAX_EXPONENT = DBL_DIG,
DIGIT_PADDING = 3,
// "+." + fDigits + "e" + fDecimalAt
MAX_DEC_DIGITS = DBL_DIG + DIGIT_PADDING + MAX_EXPONENT
MAX_DEC_DIGITS = MAX_DIGITS + DIGIT_PADDING + MAX_EXPONENT
} EDigitListValues;
U_NAMESPACE_BEGIN
@ -61,7 +64,7 @@ U_NAMESPACE_BEGIN
* derived by placing all the digits of the list to the right of the
* decimal point, by 10^exponent.
*/
class U_COMMON_API DigitList : public UMemory { // Declare external to make compiler happy
class U_I18N_API DigitList : public UMemory { // Declare external to make compiler happy
public:
DigitList();
~DigitList();
@ -125,6 +128,14 @@ public:
*/
int32_t getLong(void);
/**
* Utility routine to get the value of the digit list
* Make sure that fitsIntoInt64() is called before calling this function.
* Returns 0 if zero length.
* @return the value of the digit list, return 0 if it is zero length
*/
int64_t getInt64(void);
/**
* Return true if the number represented by this object can fit into
* a long.
@ -134,6 +145,15 @@ public:
*/
UBool fitsIntoLong(UBool ignoreNegativeZero);
/**
* Return true if the number represented by this object can fit into
* an int64_t.
* @param ignoreNegativeZero True if negative zero is ignored.
* @return true if the number represented by this object can fit into
* a long, return false otherwise.
*/
UBool fitsIntoInt64(UBool ignoreNegativeZero);
/**
* Utility routine to set the value of the digit list from a double
* Input must be non-negative, and must not be Inf, -Inf, or NaN.
@ -153,6 +173,15 @@ public:
*/
void set(int32_t source, int32_t maximumDigits = 0);
/**
* Utility routine to set the value of the digit list from an int64.
* If a non-zero maximumDigits is specified, no more than that number of
* significant digits will be produced.
* @param source The value to be set
* @param maximunDigits The maximum number of digits to be shown
*/
void set(int64_t source, int32_t maximumDigits = 0);
/**
* Return true if this is a representation of zero.
* @return true if this is a representation of zero.

View file

@ -35,7 +35,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
Formattable::Formattable()
: UObject(), fType(kLong)
{
fValue.fLong = 0;
fValue.fInt64 = 0;
}
// -------------------------------------
@ -62,7 +62,16 @@ Formattable::Formattable(double value)
Formattable::Formattable(int32_t value)
: UObject(), fType(kLong)
{
fValue.fLong = value;
fValue.fInt64 = value;
}
// -------------------------------------
// Creates a formattable object with a long value.
Formattable::Formattable(int64_t value)
: UObject(), fType(kInt64)
{
fValue.fInt64 = value;
}
// -------------------------------------
@ -141,8 +150,9 @@ Formattable::operator=(const Formattable& source)
fValue.fDouble = source.fValue.fDouble;
break;
case kLong:
case kInt64:
// Sets the long value.
fValue.fLong = source.fValue.fLong;
fValue.fInt64 = source.fValue.fInt64;
break;
case kDate:
// Sets the Date value.
@ -171,7 +181,8 @@ Formattable::operator==(const Formattable& that) const
case kDouble:
return fValue.fDouble == that.fValue.fDouble;
case kLong:
return fValue.fLong == that.fValue.fLong;
case kInt64:
return fValue.fInt64 == that.fValue.fInt64;
case kString:
return *(fValue.fString) == *(that.fValue.fString);
case kArray:
@ -239,7 +250,18 @@ Formattable::setLong(int32_t l)
{
dispose();
fType = kLong;
fValue.fLong = l;
fValue.fInt64 = l;
}
// -------------------------------------
// Sets the value to an int64 value ll.
void
Formattable::setInt64(int64_t ll)
{
dispose();
fType = kInt64;
fValue.fInt64 = ll;
}
// -------------------------------------

View file

@ -933,6 +933,14 @@ InputPath=.\unicode\decimfmt.h
# End Source File
# Begin Source File
SOURCE=.\digitlst.cpp
# End Source File
# Begin Source File
SOURCE=.\digitlst.h
# End Source File
# Begin Source File
SOURCE=.\dtfmtsym.cpp
# End Source File
# Begin Source File

View file

@ -154,6 +154,9 @@ NumberFormat::format(const Formattable& obj,
else if (obj.getType() == Formattable::kLong) {
return format(obj.getLong(), appendTo, pos);
}
else if (obj.getType() == Formattable::kInt64) {
return format(obj.getInt64(), appendTo, pos);
}
// can't try to format a non-numeric object
else {
status = U_INVALID_FORMAT_ERROR;
@ -161,6 +164,17 @@ NumberFormat::format(const Formattable& obj,
}
}
// -------------------------------------
UnicodeString&
NumberFormat::format(int64_t number,
UnicodeString& appendTo,
FieldPosition& pos) const
{
// default so we don't introduce a new abstract method
return format((int32_t)number, appendTo, pos);
}
// -------------------------------------
// Parses the string and save the result object as well
// as the final parsed position.
@ -193,6 +207,16 @@ NumberFormat::format(int32_t number, UnicodeString& appendTo) const
return format(number, appendTo, pos);
}
// -------------------------------------
// Formats a long number and save the result in a string.
UnicodeString&
NumberFormat::format(int64_t number, UnicodeString& appendTo) const
{
FieldPosition pos(0);
return format(number, appendTo, pos);
}
// -------------------------------------
// Parses the text and save the result object. If the returned
// parse position is 0, that means the parsing failed, the status

View file

@ -493,6 +493,22 @@ public:
virtual UnicodeString& format(int32_t number,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format an int64_t number using this object's choices.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @draft ICU 2.8
*/
virtual UnicodeString& format(int64_t number,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format an array of objects using this object's choices.
*

View file

@ -375,6 +375,21 @@ public:
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format an int64 number using base-10 representation.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @draft ICU 2.8
*/
virtual UnicodeString& format(int64_t number,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format a Formattable using base-10 representation.
*
* @param obj The value to be formatted.
@ -433,6 +448,19 @@ public:
UnicodeString& format(int32_t number,
UnicodeString& appendTo) const;
/**
* Redeclared NumberFormat method.
* Format an int64 number. These methods call the NumberFormat
* pure virtual format() methods with the default FieldPosition.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @return Reference to 'appendTo' parameter.
* @draft ICU 2.8
*/
UnicodeString& format(int64_t number,
UnicodeString& appendTo) const;
/**
* Parse the given string using this object's choices. The method
* does string comparisons to try to find an optimal match.
@ -1333,7 +1361,7 @@ inline UnicodeString&
DecimalFormat::format(int32_t number,
UnicodeString& appendTo) const {
FieldPosition pos(0);
return format(number, appendTo, pos);
return format((int64_t)number, appendTo, pos);
}
inline const UnicodeString &

View file

@ -75,6 +75,12 @@ public:
* @stable ICU 2.0
*/
Formattable(int32_t l);
/**
* Creates a Formattable object with an int64_t number
* @param ll the int64_t number.
* @draft ICU 2.8
*/
Formattable(int64_t ll);
/**
* Creates a Formattable object with a char string pointer.
* Assumes that the char string is null terminated.
@ -141,12 +147,19 @@ public:
* @draft ICU 2.4
*/
enum Type {
/** @draft ICU 2.4 */
kDate, // Date
/** @draft ICU 2.4 */
kDouble, // double
/** @draft ICU 2.4 */
kLong, // long
/** @draft ICU 2.4 */
kString, // UnicodeString
kArray // Formattable[]
};
/** @draft ICU 2.4 */
kArray, // Formattable[]
/** @draft ICU 2.8 */
kInt64 // int64
};
/**
* Gets the data type of this Formattable object.
@ -166,13 +179,19 @@ public:
* @return the long value of this object.
* @stable ICU 2.0
*/
int32_t getLong(void) const { return fValue.fLong; }
int32_t getLong(void) const { return (int32_t)fValue.fInt64; }
/**
* Gets the int64 value of this object.
* @return the int64 value of this object.
* @draft ICU 2.8
*/
int64_t getInt64(void) const { return fValue.fInt64; }
/**
* Gets the Date value of this object.
* @return the Date value of this object.
* @stable ICU 2.0
*/
UDate getDate(void) const { return fValue.fDate; }
UDate getDate(void) const { return fValue.fDate; }
/**
* Gets the string value of this object.
@ -226,6 +245,12 @@ public:
* @stable ICU 2.0
*/
void setLong(int32_t l);
/**
* Sets the int64 value of this object.
* @param ll the new int64 value to be set.
* @draft ICU 2.8
*/
void setInt64(int64_t ll);
/**
* Sets the Date value of this object.
* @param d the new Date value to be set.
@ -293,12 +318,12 @@ private:
union {
UnicodeString* fString;
double fDouble;
int32_t fLong;
UDate fDate;
int64_t fInt64;
UDate fDate;
struct
{
Formattable* fArray;
int32_t fCount;
int32_t fCount;
} fArrayAndCount;
} fValue;

View file

@ -247,6 +247,19 @@ public:
UnicodeString& format( int32_t number,
UnicodeString& appendTo) const;
/**
* Format an int64 number. These methods call the NumberFormat
* pure virtual format() methods with the default FieldPosition.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @return Reference to 'appendTo' parameter.
* @draft ICU 2.8
*/
UnicodeString& format( int64_t number,
UnicodeString& appendTo) const;
/**
* Format a double number. Concrete subclasses must implement
* these pure virtual methods.
@ -278,6 +291,22 @@ public:
UnicodeString& appendTo,
FieldPosition& pos) const = 0;
/**
* Format an int64 number. (Not abstract to retain compatibility
* with earlier releases, however subclasses should override this
* method as it just delegates to format(int32_t number...);
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @draft ICU 2.8
*/
virtual UnicodeString& format(int64_t number,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Redeclared Format method.
* @param obj The object to be formatted.

View file

@ -63,6 +63,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
CASE(22,TestScientific2);
CASE(23,TestScientificGrouping);
CASE(24,TestInt64);
default: name = ""; break;
}
@ -99,9 +100,6 @@ NumberFormatTest::TestAPI(void)
delete test;
}
}
// Test various patterns
@ -357,7 +355,7 @@ void
NumberFormatTest::TestScientificGrouping() {
// jb 2552
UErrorCode status = U_ZERO_ERROR;
DecimalFormat fmt("###.##E0",status);
DecimalFormat fmt("##0.00E0",status);
if (U_SUCCESS(status)) {
expect(fmt, .01234, "12.3E-3");
expect(fmt, .1234, "123E-3");
@ -368,6 +366,107 @@ NumberFormatTest::TestScientificGrouping() {
}
}
static void setFromString(DigitList& dl, const char* str) {
char c;
UBool decimalSet = FALSE;
dl.clear();
while (c = *str++) {
if (c == '-') {
dl.fIsPositive = FALSE;
} else if (c == '+') {
dl.fIsPositive = TRUE;
} else if (c == '.') {
dl.fDecimalAt = dl.fCount;
decimalSet = TRUE;
} else {
dl.append(c);
}
}
if (!decimalSet) {
dl.fDecimalAt = dl.fCount;
}
}
void
NumberFormatTest::TestInt64() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormat fmt("#.#E0",status);
fmt.setMaximumFractionDigits(20);
if (U_SUCCESS(status)) {
expect(fmt, (int64_t)0, "0E0");
expect(fmt, (int64_t)-1, "-1E0");
expect(fmt, (int64_t)1, "1E0");
expect(fmt, (int64_t)2147483647, "2.147483647E9");
expect(fmt, (int64_t)-2147483647-1, "-2.147483648E9");
expect(fmt, (int64_t)9223372036854775807, "9.223372036854775807E18");
expect(fmt, (int64_t)-9223372036854775807-1, "-9.223372036854775808E18");
}
// also test digitlist
int64_t int64max = 9223372036854775807;
int64_t int64min = -9223372036854775807 - 1;
const char* int64maxstr = "9223372036854775807";
const char* int64minstr = "-9223372036854775808";
UnicodeString fail("fail: ");
// test max int64 value
DigitList dl;
setFromString(dl, int64maxstr);
{
if (!dl.fitsIntoInt64(FALSE)) {
errln(fail + int64maxstr + " didn't fit");
}
int64_t int64Value = dl.getInt64();
if (int64Value != int64max) {
errln(fail + int64maxstr);
}
dl.set(int64Value);
int64Value = dl.getInt64();
if (int64Value != int64max) {
errln(fail + int64maxstr);
}
}
// test negative of max int64 value (1 shy of min int64 value)
dl.fIsPositive = FALSE;
{
if (!dl.fitsIntoInt64(FALSE)) {
errln(fail + "-" + int64maxstr + " didn't fit");
}
int64_t int64Value = dl.getInt64();
if (int64Value != -int64max) {
errln(fail + "-" + int64maxstr);
}
dl.set(int64Value);
int64Value = dl.getInt64();
if (int64Value != -int64max) {
errln(fail + "-" + int64maxstr);
}
}
// test min int64 value
setFromString(dl, int64minstr);
{
if (!dl.fitsIntoInt64(FALSE)) {
errln(fail + "-" + int64minstr + " didn't fit");
}
int64_t int64Value = dl.getInt64();
if (int64Value != int64min) {
errln(fail + int64minstr);
}
dl.set(int64Value);
int64Value = dl.getInt64();
if (int64Value != -int64max) {
errln(fail + "-" + int64maxstr);
}
}
// test negative of min int 64 value (1 more than max int64 value)
dl.fIsPositive = TRUE; // won't fit
{
if (dl.fitsIntoInt64(FALSE)) {
errln(fail + "-(" + int64minstr + ") didn't fit");
}
}
}
// -------------------------------------
// Test the handling of quotes

View file

@ -79,6 +79,8 @@ class NumberFormatTest: public CalendarTimeZoneTest {
void TestScientificGrouping(void);
void TestInt64(void);
void TestSurrogateSupport(void);
/**

View file

@ -1916,10 +1916,16 @@ NumberFormatRegressionTest::Test4162198(void)
//}
//logln("The string " + s + " parsed as " + n);
if(n.getDouble() != dbl) {
errln("Round trip failure");
}
// {dlf} The old code assumes n is a double, but it isn't any more...
// Formattable apparently does not and never did interconvert... too bad.
//if(n.getDouble() != dbl) {
// errln("Round trip failure");
//}
if (n.getInt64() != dbl) {
errln("Round trip failure");
}
delete f;
}

View file

@ -22,6 +22,7 @@ static const char * formattableTypeName(Formattable::Type t)
case Formattable::kLong: return "kLong";
case Formattable::kString: return "kString";
case Formattable::kArray: return "kArray";
case Formattable::kInt64: return "kInt64";
default: return "??unknown??";
}
}
@ -292,6 +293,8 @@ IntlTestNumberFormat::tryIt(double aNumber)
// Convert from long to double
if (number[i].getType() == Formattable::kLong)
number[i].setDouble(number[i].getLong());
else if (number[i].getType() == Formattable::kInt64)
number[i].setDouble(number[i].getInt64());
else if (number[i].getType() != Formattable::kDouble)
{
errMsg = ("**** FAIL: Parse of " + prettify(string[i-1])