mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 23:10:40 +00:00
ICU-9258 merge from branches, performance improvements
X-SVN-Rev: 31881
This commit is contained in:
parent
5c95e765c1
commit
43b918a0c8
18 changed files with 947 additions and 93 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2011, International Business Machines
|
||||
* Copyright (C) 2002-2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
@ -36,8 +36,23 @@ static UMemFreeFn *pFree;
|
|||
* Used to prevent changing out the heap functions after allocations have been made */
|
||||
static UBool gHeapInUse;
|
||||
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
#include <stdio.h>
|
||||
static int n=0;
|
||||
static long b=0;
|
||||
#endif
|
||||
|
||||
|
||||
U_CAPI void * U_EXPORT2
|
||||
uprv_malloc(size_t s) {
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
#if 1
|
||||
putchar('>');
|
||||
fflush(stdout);
|
||||
#else
|
||||
fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr);
|
||||
#endif
|
||||
#endif
|
||||
if (s > 0) {
|
||||
gHeapInUse = TRUE;
|
||||
if (pAlloc) {
|
||||
|
@ -52,6 +67,10 @@ uprv_malloc(size_t s) {
|
|||
|
||||
U_CAPI void * U_EXPORT2
|
||||
uprv_realloc(void * buffer, size_t size) {
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
putchar('~');
|
||||
fflush(stdout);
|
||||
#endif
|
||||
if (buffer == zeroMem) {
|
||||
return uprv_malloc(size);
|
||||
} else if (size == 0) {
|
||||
|
@ -73,6 +92,10 @@ uprv_realloc(void * buffer, size_t size) {
|
|||
|
||||
U_CAPI void U_EXPORT2
|
||||
uprv_free(void *buffer) {
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
putchar('<');
|
||||
fflush(stdout);
|
||||
#endif
|
||||
if (buffer != zeroMem) {
|
||||
if (pFree) {
|
||||
(*pFree)(pContext, buffer);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1997-2011, International Business Machines
|
||||
* Copyright (C) 1997-2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
@ -29,6 +29,10 @@
|
|||
#include "unicode/utypes.h"
|
||||
#include "unicode/localpointer.h"
|
||||
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
|
||||
#define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
|
||||
#define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
|
||||
|
@ -331,6 +335,9 @@ private:
|
|||
template<typename T, int32_t stackCapacity>
|
||||
inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
|
||||
if(newCapacity>0) {
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T));
|
||||
#endif
|
||||
T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
|
||||
if(p!=NULL) {
|
||||
if(length>0) {
|
||||
|
@ -365,6 +372,9 @@ inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32
|
|||
length=capacity;
|
||||
}
|
||||
p=(T *)uprv_malloc(length*sizeof(T));
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
|
||||
#endif
|
||||
if(p==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -501,6 +511,9 @@ template<typename H, typename T, int32_t stackCapacity>
|
|||
inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
|
||||
int32_t length) {
|
||||
if(newCapacity>=0) {
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
|
||||
#endif
|
||||
H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
|
||||
if(p!=NULL) {
|
||||
if(length<0) {
|
||||
|
@ -537,6 +550,9 @@ inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t l
|
|||
} else if(length>capacity) {
|
||||
length=capacity;
|
||||
}
|
||||
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
||||
::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
|
||||
#endif
|
||||
p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
|
||||
if(p==NULL) {
|
||||
return NULL;
|
||||
|
|
|
@ -404,4 +404,38 @@
|
|||
# define UCONFIG_NO_SERVICE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def UCONFIG_INTERNAL_DIGITLIST
|
||||
* This switch turns on the fast but binary-incompatible Formattable class with an internal DigitList
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
#ifndef UCONFIG_INTERNAL_DIGITLIST
|
||||
# define UCONFIG_INTERNAL_DIGITLIST 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \def UCONFIG_HAVE_PARSEALLINPUT
|
||||
* This switch turns on the "parse all input" attribute. Binary incompatible.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
#ifndef UCONFIG_HAVE_PARSEALLINPUT
|
||||
# define UCONFIG_HAVE_PARSEALLINPUT 0
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \def UCONFIG_HAVE_PARSEALLINPUT
|
||||
* This switch turns on other formatting fastpaths. Binary incompatible in object DecimalFormat and DecimalFormatSymbols
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
#ifndef UCONFIG_FORMAT_FASTPATHS_49
|
||||
# define UCONFIG_FORMAT_FASTPATHS_49 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
43
icu4c/source/i18n/dcfmtimp.h
Normal file
43
icu4c/source/i18n/dcfmtimp.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef DCFMTIMP_H
|
||||
#define DCFMTIMP_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
enum EDecimalFormatFastpathStatus {
|
||||
kFastpathNO = 0,
|
||||
kFastpathYES = 1,
|
||||
kFastpathUNKNOWN = 2, /* not yet set */
|
||||
};
|
||||
|
||||
/**
|
||||
* Must be smaller than DecimalFormat::fReserved
|
||||
*/
|
||||
struct DecimalFormatInternal {
|
||||
uint8_t fFastpathStatus;
|
||||
|
||||
#ifdef FMT_DEBUG
|
||||
void dump() const {
|
||||
printf("DecimalFormatInternal: fFastpathStatus=%c\n",
|
||||
"NY?"[(int)fFastpathStatus&3]);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -69,10 +69,22 @@
|
|||
#include <math.h>
|
||||
#include "hash.h"
|
||||
#include "decfmtst.h"
|
||||
|
||||
#include "dcfmtimp.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/* == Fastpath calculation. ==
|
||||
*/
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
inline DecimalFormatInternal& internalData(uint8_t *reserved) {
|
||||
return *reinterpret_cast<DecimalFormatInternal*>(reserved);
|
||||
}
|
||||
inline const DecimalFormatInternal& internalData(const uint8_t *reserved) {
|
||||
return *reinterpret_cast<const DecimalFormatInternal*>(reserved);
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
/* For currency parsing purose,
|
||||
* Need to remember all prefix patterns and suffix patterns of
|
||||
* every currency format pattern,
|
||||
|
@ -180,12 +192,15 @@ U_CDECL_END
|
|||
|
||||
#ifdef FMT_DEBUG
|
||||
#include <stdio.h>
|
||||
static void debugout(UnicodeString s) {
|
||||
static void _debugout(const char *f, int l, const UnicodeString& s) {
|
||||
char buf[2000];
|
||||
s.extract((int32_t) 0, s.length(), buf);
|
||||
printf("%s\n", buf);
|
||||
printf("%s:%d: %s\n", f,l, buf);
|
||||
}
|
||||
#define debug(x) printf("%s\n", x);
|
||||
#define debugout(x) _debugout(__FILE__,__LINE__,x)
|
||||
#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
|
||||
static const UnicodeString dbg_null("<NULL>","");
|
||||
#define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
|
||||
#else
|
||||
#define debugout(x)
|
||||
#define debug(x)
|
||||
|
@ -247,7 +262,7 @@ inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
|
|||
// Constructs a DecimalFormat instance in the default locale.
|
||||
|
||||
DecimalFormat::DecimalFormat(UErrorCode& status) {
|
||||
init();
|
||||
init(status);
|
||||
UParseError parseError;
|
||||
construct(status, parseError);
|
||||
}
|
||||
|
@ -258,7 +273,7 @@ DecimalFormat::DecimalFormat(UErrorCode& status) {
|
|||
|
||||
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
||||
UErrorCode& status) {
|
||||
init();
|
||||
init(status);
|
||||
UParseError parseError;
|
||||
construct(status, parseError, &pattern);
|
||||
}
|
||||
|
@ -271,7 +286,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
|||
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
||||
DecimalFormatSymbols* symbolsToAdopt,
|
||||
UErrorCode& status) {
|
||||
init();
|
||||
init(status);
|
||||
UParseError parseError;
|
||||
if (symbolsToAdopt == NULL)
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -282,7 +297,7 @@ DecimalFormat::DecimalFormat( const UnicodeString& pattern,
|
|||
DecimalFormatSymbols* symbolsToAdopt,
|
||||
UParseError& parseErr,
|
||||
UErrorCode& status) {
|
||||
init();
|
||||
init(status);
|
||||
if (symbolsToAdopt == NULL)
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
construct(status,parseErr, &pattern, symbolsToAdopt);
|
||||
|
@ -296,7 +311,7 @@ DecimalFormat::DecimalFormat( const UnicodeString& pattern,
|
|||
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
||||
const DecimalFormatSymbols& symbols,
|
||||
UErrorCode& status) {
|
||||
init();
|
||||
init(status);
|
||||
UParseError parseError;
|
||||
construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
|
||||
}
|
||||
|
@ -310,7 +325,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
|||
DecimalFormatSymbols* symbolsToAdopt,
|
||||
UNumberFormatStyle style,
|
||||
UErrorCode& status) {
|
||||
init();
|
||||
init(status);
|
||||
fStyle = style;
|
||||
UParseError parseError;
|
||||
construct(status, parseError, &pattern, symbolsToAdopt);
|
||||
|
@ -321,7 +336,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
|||
// Put all fields of an uninitialized object into a known state.
|
||||
// Common code, shared by all constructors.
|
||||
void
|
||||
DecimalFormat::init() {
|
||||
DecimalFormat::init(UErrorCode &status) {
|
||||
fPosPrefixPattern = 0;
|
||||
fPosSuffixPattern = 0;
|
||||
fNegPrefixPattern = 0;
|
||||
|
@ -349,6 +364,16 @@ DecimalFormat::init() {
|
|||
fAffixesForCurrency = NULL;
|
||||
fPluralAffixesForCurrency = NULL;
|
||||
fCurrencyPluralInfo = NULL;
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
fParseAllInput = UNUM_MAYBE;
|
||||
#endif
|
||||
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
DecimalFormatInternal &data = internalData(fReserved);
|
||||
data.fFastpathStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
|
||||
#endif
|
||||
// only do this once per obj.
|
||||
DecimalFormatStaticSets::initSets(&status);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -489,6 +514,11 @@ DecimalFormat::construct(UErrorCode& status,
|
|||
if (fCurrencySignCount > fgCurrencySignCountZero) {
|
||||
setCurrencyInternally(getCurrency(), status);
|
||||
}
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
DecimalFormatInternal &data = internalData(fReserved);
|
||||
data.fFastpathStatus = kFastpathNO; // allow it to be calculated
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -654,7 +684,8 @@ DecimalFormat::~DecimalFormat()
|
|||
|
||||
DecimalFormat::DecimalFormat(const DecimalFormat &source) :
|
||||
NumberFormat(source) {
|
||||
init();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
init(status); // if this fails, 'source' isn't initialized properly either.
|
||||
*this = source;
|
||||
}
|
||||
|
||||
|
@ -744,6 +775,9 @@ DecimalFormat::operator=(const DecimalFormat& rhs)
|
|||
copyHashForAffix(rhs.fPluralAffixesForCurrency, fPluralAffixesForCurrency, status);
|
||||
}
|
||||
}
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -966,6 +1000,43 @@ DecimalFormat::format(int32_t number,
|
|||
return format((int64_t)number, appendTo, posIter, status);
|
||||
}
|
||||
|
||||
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
void DecimalFormat::handleChanged() {
|
||||
DecimalFormatInternal &data = internalData(fReserved);
|
||||
|
||||
if(data.fFastpathStatus == kFastpathUNKNOWN) {
|
||||
return; // still constructing. Wait.
|
||||
}
|
||||
|
||||
data.fFastpathStatus = kFastpathNO;
|
||||
|
||||
if (fGroupingSize!=0) {
|
||||
debug("No fastpath: fGroupingSize!=0"); // TODO: revisit, should handle ex. up to 999 if groupingsize is 3.
|
||||
} else if(fGroupingSize2!=0) {
|
||||
debug("No fastpath: fGroupingSize2!=0");
|
||||
} else if(fUseExponentialNotation) {
|
||||
debug("No fastpath: fUseExponentialNotation");
|
||||
} else if(fFormatWidth!=0) {
|
||||
debug("No fastpath: fFormatWidth!=0");
|
||||
} else if(fMinSignificantDigits!=1) {
|
||||
debug("No fastpath: fMinSignificantDigits!=1");
|
||||
} else if(fMultiplier!=NULL) {
|
||||
debug("No fastpath: fMultiplier!=NULL");
|
||||
} else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)) {
|
||||
debug("No fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)");
|
||||
} else if(fDecimalSeparatorAlwaysShown) {
|
||||
debug("No fastpath: fDecimalSeparatorAlwaysShown");
|
||||
} else if(getMinimumFractionDigits()>0) {
|
||||
debug("No fastpath: fMinFractionDigits>0");
|
||||
} else if(fCurrencySignCount > fgCurrencySignCountZero) {
|
||||
debug("No fastpath: fCurrencySignCount > fgCurrencySignCountZero");
|
||||
} else {
|
||||
data.fFastpathStatus = kFastpathYES;
|
||||
debug("kFastpathYES!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
|
@ -973,8 +1044,8 @@ DecimalFormat::format(int64_t number,
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition) const
|
||||
{
|
||||
FieldPositionOnlyHandler handler(fieldPosition);
|
||||
return _format(number, appendTo, handler);
|
||||
FieldPositionOnlyHandler handler(fieldPosition);
|
||||
return _format(number, appendTo, handler);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
|
@ -992,7 +1063,76 @@ DecimalFormat::_format(int64_t number,
|
|||
UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler) const
|
||||
{
|
||||
// Bottleneck function for formatting int64_t
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
// const UnicodeString *posPrefix = fPosPrefixPattern;
|
||||
// const UnicodeString *posSuffix = fPosSuffixPattern;
|
||||
// const UnicodeString *negSuffix = fNegSuffixPattern;
|
||||
|
||||
const DecimalFormatInternal &data = internalData(fReserved);
|
||||
|
||||
#ifdef FMT_DEBUG
|
||||
data.dump();
|
||||
printf("fastpath? [%d]\n", number);
|
||||
#endif
|
||||
|
||||
if( data.fFastpathStatus==kFastpathYES ) {
|
||||
|
||||
#define kZero 0x0030
|
||||
const int32_t MAX_IDX = MAX_DIGITS+2;
|
||||
UChar outputStr[MAX_IDX];
|
||||
int32_t destIdx = MAX_IDX;
|
||||
outputStr[--destIdx] = 0; // term
|
||||
|
||||
int64_t n = number;
|
||||
if (number < 0) { // Negative numbers are slightly larger than a postive
|
||||
//outputStr[--destIdx] = (char)(-(n % 10) + kZero);
|
||||
n *= -1;
|
||||
}
|
||||
do {
|
||||
outputStr[--destIdx] = (n % 10) + kZero;
|
||||
n /= 10;
|
||||
} while (n > 0);
|
||||
|
||||
|
||||
// Slide the number to the start of the output str
|
||||
U_ASSERT(destIdx >= 0);
|
||||
int32_t length = MAX_IDX - destIdx -1;
|
||||
//uprv_memmove(outputStr, outputStr+MAX_IDX-length, length);
|
||||
int32_t prefixLen = appendAffix(appendTo, number, handler, number<0, TRUE);
|
||||
|
||||
int32_t maxIntDig = getMaximumIntegerDigits();
|
||||
int32_t prependZero = getMinimumIntegerDigits() - length;
|
||||
|
||||
#ifdef FMT_DEBUG
|
||||
printf("prependZero=%d, length=%d, minintdig=%d\n", prependZero, length, getMinimumIntegerDigits());
|
||||
#endif
|
||||
int32_t intBegin = appendTo.length();
|
||||
|
||||
while((prependZero--)>0) {
|
||||
appendTo.append(0x0030); // '0'
|
||||
}
|
||||
|
||||
appendTo.append(outputStr+destIdx, length);
|
||||
handler.addAttribute(kIntegerField, intBegin, appendTo.length());
|
||||
|
||||
int32_t suffixLen = appendAffix(appendTo, number, handler, number<0, FALSE);
|
||||
|
||||
//outputStr[length]=0;
|
||||
|
||||
#ifdef FMT_DEBUG
|
||||
printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr+destIdx, length, MAX_IDX, number);
|
||||
#endif
|
||||
|
||||
#undef kZero
|
||||
|
||||
return appendTo;
|
||||
} // end fastpath
|
||||
#endif
|
||||
|
||||
// Else the slow way - via DigitList
|
||||
DigitList digits;
|
||||
digits.set(number);
|
||||
return _format(digits, appendTo, handler, status);
|
||||
|
@ -1055,6 +1195,47 @@ DecimalFormat::format(const StringPiece &number,
|
|||
FieldPositionIterator *posIter,
|
||||
UErrorCode &status) const
|
||||
{
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
// don't bother if the int64 path is not optimized
|
||||
int32_t len = number.length();
|
||||
|
||||
if(len>0&&len<10) { /* 10 or more digits may not be an int64 */
|
||||
const char *data = number.data();
|
||||
int64_t num = 0;
|
||||
UBool neg = FALSE;
|
||||
UBool ok = TRUE;
|
||||
|
||||
int32_t start = 0;
|
||||
|
||||
if(data[start]=='+') {
|
||||
start++;
|
||||
} else if(data[start]=='-') {
|
||||
neg=TRUE;
|
||||
start++;
|
||||
}
|
||||
|
||||
int32_t place = 1; /* 1, 10, ... */
|
||||
for(int32_t i=len-1;i>=start;i--) {
|
||||
if(data[i]>='0'&&data[i]<='9') {
|
||||
num+=place*(int64_t)(data[i]-'0');
|
||||
} else {
|
||||
ok=FALSE;
|
||||
break;
|
||||
}
|
||||
place *= 10;
|
||||
}
|
||||
|
||||
if(ok) {
|
||||
if(neg) {
|
||||
num = -num;// add minus bit
|
||||
}
|
||||
// format as int64_t
|
||||
return format(num, toAppendTo, posIter, status);
|
||||
}
|
||||
// else fall through
|
||||
}
|
||||
#endif
|
||||
|
||||
DigitList dnum;
|
||||
dnum.set(number, status);
|
||||
if (U_FAILURE(status)) {
|
||||
|
@ -1672,7 +1853,12 @@ void DecimalFormat::parse(const UnicodeString& text,
|
|||
|
||||
// status is used to record whether a number is infinite.
|
||||
UBool status[fgStatusLength];
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer
|
||||
#else
|
||||
DigitList *digits = new DigitList;
|
||||
#endif
|
||||
if (digits == NULL) {
|
||||
return; // no way to report error from here.
|
||||
}
|
||||
|
@ -1680,8 +1866,10 @@ void DecimalFormat::parse(const UnicodeString& text,
|
|||
if (fCurrencySignCount > fgCurrencySignCountZero) {
|
||||
if (!parseForCurrency(text, parsePosition, *digits,
|
||||
status, currency)) {
|
||||
delete digits;
|
||||
return;
|
||||
#if !UCONFIG_INTERNAL_DIGITLIST
|
||||
delete digits;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!subparse(text,
|
||||
|
@ -1689,8 +1877,11 @@ void DecimalFormat::parse(const UnicodeString& text,
|
|||
fPosPrefixPattern, fPosSuffixPattern,
|
||||
FALSE, UCURR_SYMBOL_NAME,
|
||||
parsePosition, *digits, status, currency)) {
|
||||
debug("!subparse(...) - rewind");
|
||||
parsePosition.setIndex(startIdx);
|
||||
#if !UCONFIG_INTERNAL_DIGITLIST
|
||||
delete digits;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1699,7 +1890,10 @@ void DecimalFormat::parse(const UnicodeString& text,
|
|||
if (status[fgStatusInfinite]) {
|
||||
double inf = uprv_getInfinity();
|
||||
result.setDouble(digits->isPositive() ? inf : -inf);
|
||||
delete digits; // TODO: set the dl to infinity, and let it fall into the code below.
|
||||
#if !UCONFIG_INTERNAL_DIGITLIST
|
||||
delete digits;
|
||||
#endif
|
||||
// TODO: set the dl to infinity, and let it fall into the code below.
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -1878,8 +2072,121 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
|
||||
int32_t position = parsePosition.getIndex();
|
||||
int32_t oldStart = position;
|
||||
int32_t textLength = text.length(); // One less pointer to follow
|
||||
UBool strictParse = !isLenient();
|
||||
UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
|
||||
#ifdef FMT_DEBUG
|
||||
UChar dbgbuf[300];
|
||||
UnicodeString s(dbgbuf,0,300);;
|
||||
s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " );
|
||||
#define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "=")); if(x->isEmpty()) { s.append(UnicodeString("<empty>")); } else { s.append(*x); } s.append(UnicodeString(" ")); }
|
||||
DBGAPPD(negPrefix);
|
||||
DBGAPPD(negSuffix);
|
||||
DBGAPPD(posPrefix);
|
||||
DBGAPPD(posSuffix);
|
||||
debugout(s);
|
||||
printf("currencyParsing=%d, fFormatWidth=%d, text.length=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, text.length(), negPrefix!=NULL?negPrefix->length():-1);
|
||||
#endif
|
||||
|
||||
UBool fastParseOk = false; /* TRUE iff fast parse is OK */
|
||||
UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
|
||||
|
||||
if(!currencyParsing &&
|
||||
|
||||
|
||||
( (
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
fParseAllInput == UNUM_YES ) ||
|
||||
( fParseAllInput == UNUM_MAYBE &&
|
||||
#endif
|
||||
fFormatWidth==0 &&
|
||||
// (negPrefix!=NULL&&negPrefix->isEmpty()) ||
|
||||
text.length()>0 &&
|
||||
text.length()<20 &&
|
||||
(posPrefix==NULL||posPrefix->isEmpty()) &&
|
||||
(posSuffix==NULL||posSuffix->isEmpty()) &&
|
||||
// (negPrefix==NULL||negPrefix->isEmpty()) &&
|
||||
// (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
|
||||
TRUE
|
||||
)
|
||||
)) { // optimized path
|
||||
int j=position;
|
||||
int l=text.length();
|
||||
int digitCount=0;
|
||||
UChar32 ch = text.char32At(j);
|
||||
const UnicodeString *decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
|
||||
UChar32 decimalChar = 0;
|
||||
int32_t decimalCount = decimalString->countChar32(0,3);
|
||||
if(isParseIntegerOnly()) {
|
||||
decimalChar = 0; // not allowed
|
||||
} else if(decimalCount==1) {
|
||||
decimalChar = decimalString->char32At(0);
|
||||
} else if(decimalCount==0) {
|
||||
decimalChar=0;
|
||||
} else {
|
||||
j=l+1;//=break
|
||||
}
|
||||
|
||||
if(ch=='-') {
|
||||
/* for now- no negs. */
|
||||
j=l+1;//=break
|
||||
|
||||
/*
|
||||
parsedNum.append('-',err);
|
||||
j+=U16_LENGTH(ch);
|
||||
if(j<l) ch = text.char32At(j);
|
||||
*/
|
||||
} else {
|
||||
parsedNum.append('+',err);
|
||||
}
|
||||
while(j<l) {
|
||||
int32_t digit = ch - zero;
|
||||
if(digit >=0 && digit <= 9) {
|
||||
parsedNum.append((char)(digit + '0'), err);
|
||||
if((digitCount>0) || digit!=0 || j==(l-1)) {
|
||||
digitCount++;
|
||||
}
|
||||
} else if(ch == decimalChar) {
|
||||
parsedNum.append((char)('.'), err);
|
||||
decimalChar=0; // no more decimals.
|
||||
fastParseHadDecimal=TRUE;
|
||||
} else {
|
||||
digitCount=-1; // fail
|
||||
break;
|
||||
}
|
||||
j+=U16_LENGTH(ch);
|
||||
ch = text.char32At(j); // for next
|
||||
}
|
||||
if(j==l && (digitCount>0)) {
|
||||
#ifdef FMT_DEBUG
|
||||
printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j, parsedNum.data(), digitCount, fGroupingSize, fGroupingSize2);
|
||||
#endif
|
||||
fastParseOk=true; // Fast parse OK!
|
||||
|
||||
#ifdef SKIP_OPT
|
||||
debug("SKIP_OPT");
|
||||
/* for testing, try it the slow way. also */
|
||||
fastParseOk=false;
|
||||
parsedNum.clear();
|
||||
#else
|
||||
parsePosition.setIndex(position=j);
|
||||
status[fgStatusInfinite]=false;
|
||||
#endif
|
||||
} else {
|
||||
// was not OK. reset, retry
|
||||
#ifdef FMT_DEBUG
|
||||
printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount);
|
||||
#endif
|
||||
parsedNum.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if(!fastParseOk
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
&& fParseAllInput!=UNUM_YES
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Match padding before prefix
|
||||
if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) {
|
||||
position = skipPadding(text, position);
|
||||
|
@ -1935,7 +2242,6 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
// put only significant digits into the DigitList, and adjust the
|
||||
// exponent as needed.
|
||||
|
||||
UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
|
||||
|
||||
UBool strictFail = FALSE; // did we exit with a strict parse failure?
|
||||
int32_t lastGroup = -1; // where did we last see a grouping separator?
|
||||
|
@ -1948,10 +2254,14 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
} else {
|
||||
decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
|
||||
}
|
||||
UChar32 decimalChar = decimalString->char32At(0);
|
||||
|
||||
const UnicodeString *groupingString = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
|
||||
UChar32 decimalChar = decimalString->char32At(0);
|
||||
UChar32 groupingChar = groupingString->char32At(0);
|
||||
int32_t decimalStringLength = decimalString->length();
|
||||
int32_t decimalCharLength = U16_LENGTH(decimalChar);
|
||||
int32_t groupingStringLength = groupingString->length();
|
||||
int32_t groupingCharLength = U16_LENGTH(groupingChar);
|
||||
|
||||
UBool sawDecimal = FALSE;
|
||||
UChar32 sawDecimalChar = 0xFFFF;
|
||||
UBool sawGrouping = FALSE;
|
||||
|
@ -1959,11 +2269,6 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
UBool sawDigit = FALSE;
|
||||
int32_t backup = -1;
|
||||
int32_t digit;
|
||||
int32_t textLength = text.length(); // One less pointer to follow
|
||||
int32_t decimalStringLength = decimalString->length();
|
||||
int32_t decimalCharLength = U16_LENGTH(decimalChar);
|
||||
int32_t groupingStringLength = groupingString->length();
|
||||
int32_t groupingCharLength = U16_LENGTH(groupingChar);
|
||||
|
||||
// equivalent grouping and decimal support
|
||||
const UnicodeSet *decimalSet = NULL;
|
||||
|
@ -2185,6 +2490,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
|
||||
parsePosition.setIndex(oldStart);
|
||||
parsePosition.setErrorIndex(position);
|
||||
debug("strictFail!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -2195,6 +2501,10 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
// parse "$" with pattern "$#0.00". (return index 0 and error index
|
||||
// 1).
|
||||
if (!sawDigit && digitCount == 0) {
|
||||
#ifdef FMT_DEBUG
|
||||
debug("none of text rec");
|
||||
printf("position=%d\n",position);
|
||||
#endif
|
||||
parsePosition.setIndex(oldStart);
|
||||
parsePosition.setErrorIndex(oldStart);
|
||||
return FALSE;
|
||||
|
@ -2226,6 +2536,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
// Fail if neither or both
|
||||
if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) {
|
||||
parsePosition.setErrorIndex(position);
|
||||
debug("neither or both");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -2239,15 +2550,34 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
parsePosition.setIndex(position);
|
||||
|
||||
parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-';
|
||||
|
||||
if(parsePosition.getIndex() == oldStart)
|
||||
#ifdef FMT_DEBUG
|
||||
printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err));
|
||||
#endif
|
||||
} /* end SLOW parse */
|
||||
if(parsePosition.getIndex() == oldStart)
|
||||
{
|
||||
#ifdef FMT_DEBUG
|
||||
printf(" PP didnt move, err\n");
|
||||
#endif
|
||||
parsePosition.setErrorIndex(position);
|
||||
return FALSE;
|
||||
}
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength)
|
||||
{
|
||||
#ifdef FMT_DEBUG
|
||||
printf(" PP didnt consume all (UNUM_YES), err\n");
|
||||
#endif
|
||||
parsePosition.setErrorIndex(position);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
digits.set(parsedNum.toStringPiece(), err);
|
||||
|
||||
if (U_FAILURE(err)) {
|
||||
#ifdef FMT_DEBUG
|
||||
printf(" err setting %s\n", u_errorName(err));
|
||||
#endif
|
||||
parsePosition.setErrorIndex(position);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -2345,8 +2675,6 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
|
|||
int32_t affixCharLength = U16_LENGTH(affixChar);
|
||||
UnicodeSet *affixSet;
|
||||
|
||||
DecimalFormatStaticSets::initSets(&status);
|
||||
|
||||
if (!lenient) {
|
||||
affixSet = DecimalFormatStaticSets::gStaticSets->fStrictDashEquivalents;
|
||||
|
||||
|
@ -2707,6 +3035,9 @@ DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
|
|||
setCurrencyForSymbols();
|
||||
}
|
||||
expandAffixes(NULL);
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Setting the symbols is equlivalent to adopting a newly created localized
|
||||
|
@ -2716,6 +3047,9 @@ void
|
|||
DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
|
||||
{
|
||||
adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -2745,12 +3079,18 @@ DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt)
|
|||
}
|
||||
}
|
||||
}
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info)
|
||||
{
|
||||
adoptCurrencyPluralInfo(info.clone());
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -2791,6 +3131,9 @@ DecimalFormat::setCurrencyForSymbols() {
|
|||
}
|
||||
ec = U_ZERO_ERROR; // reset local error code!
|
||||
setCurrencyInternally(c, ec);
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -2813,6 +3156,9 @@ DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
|
|||
fPositivePrefix = newValue;
|
||||
delete fPosPrefixPattern;
|
||||
fPosPrefixPattern = 0;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -2834,6 +3180,9 @@ DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
|
|||
fNegativePrefix = newValue;
|
||||
delete fNegPrefixPattern;
|
||||
fNegPrefixPattern = 0;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -2855,6 +3204,9 @@ DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
|
|||
fPositiveSuffix = newValue;
|
||||
delete fPosSuffixPattern;
|
||||
fPosSuffixPattern = 0;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -2876,6 +3228,9 @@ DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
|
|||
fNegativeSuffix = newValue;
|
||||
delete fNegSuffixPattern;
|
||||
fNegSuffixPattern = 0;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -2916,6 +3271,9 @@ DecimalFormat::setMultiplier(int32_t newValue)
|
|||
fMultiplier->set(newValue);
|
||||
}
|
||||
}
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2957,6 +3315,9 @@ void DecimalFormat::setRoundingIncrement(double newValue) {
|
|||
// or fRoundingIncrement could not be created.
|
||||
delete fRoundingIncrement;
|
||||
fRoundingIncrement = NULL;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2980,6 +3341,9 @@ DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
|
|||
*/
|
||||
void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
|
||||
fRoundingMode = roundingMode;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3009,6 +3373,9 @@ int32_t DecimalFormat::getFormatWidth() const {
|
|||
*/
|
||||
void DecimalFormat::setFormatWidth(int32_t width) {
|
||||
fFormatWidth = (width > 0) ? width : 0;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
UnicodeString DecimalFormat::getPadCharacterString() const {
|
||||
|
@ -3022,6 +3389,9 @@ void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
|
|||
else {
|
||||
fPad = kDefaultPad;
|
||||
}
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3066,6 +3436,9 @@ DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
|
|||
*/
|
||||
void DecimalFormat::setPadPosition(EPadPosition padPos) {
|
||||
fPadPosition = padPos;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3093,6 +3466,9 @@ UBool DecimalFormat::isScientificNotation() {
|
|||
*/
|
||||
void DecimalFormat::setScientificNotation(UBool useScientific) {
|
||||
fUseExponentialNotation = useScientific;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3121,6 +3497,9 @@ int8_t DecimalFormat::getMinimumExponentDigits() const {
|
|||
*/
|
||||
void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
|
||||
fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3152,6 +3531,9 @@ UBool DecimalFormat::isExponentSignAlwaysShown() {
|
|||
*/
|
||||
void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
|
||||
fExponentSignAlwaysShown = expSignAlways;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -3171,6 +3553,9 @@ void
|
|||
DecimalFormat::setGroupingSize(int32_t newValue)
|
||||
{
|
||||
fGroupingSize = newValue;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -3187,6 +3572,9 @@ void
|
|||
DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
|
||||
{
|
||||
fGroupingSize2 = newValue;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -3205,6 +3593,9 @@ void
|
|||
DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
|
||||
{
|
||||
fDecimalSeparatorAlwaysShown = newValue;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -3255,13 +3646,13 @@ void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) {
|
|||
}
|
||||
#ifdef FMT_DEBUG
|
||||
UnicodeString s;
|
||||
s.append("[")
|
||||
.append(*fPosPrefixPattern).append("|").append(*fPosSuffixPattern)
|
||||
.append(";") .append(*fNegPrefixPattern).append("|").append(*fNegSuffixPattern)
|
||||
.append("]->[")
|
||||
.append(fPositivePrefix).append("|").append(fPositiveSuffix)
|
||||
.append(";") .append(fNegativePrefix).append("|").append(fNegativeSuffix)
|
||||
.append("]\n");
|
||||
s.append(UnicodeString("["))
|
||||
.append(DEREFSTR(fPosPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fPosSuffixPattern))
|
||||
.append((UnicodeString)";") .append(DEREFSTR(fNegPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fNegSuffixPattern))
|
||||
.append((UnicodeString)"]->[")
|
||||
.append(fPositivePrefix).append((UnicodeString)"|").append(fPositiveSuffix)
|
||||
.append((UnicodeString)";") .append(fNegativePrefix).append((UnicodeString)"|").append(fNegativeSuffix)
|
||||
.append((UnicodeString)"]\n");
|
||||
debugout(s);
|
||||
#endif
|
||||
}
|
||||
|
@ -4533,7 +4924,7 @@ DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString& pattern,
|
|||
}
|
||||
#ifdef FMT_DEBUG
|
||||
UnicodeString s;
|
||||
s.append("\"").append(pattern).append("\"->");
|
||||
s.append((UnicodeString)"\"").append(pattern).append((UnicodeString)"\"->");
|
||||
debugout(s);
|
||||
#endif
|
||||
|
||||
|
@ -4577,6 +4968,9 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
|
|||
}
|
||||
applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
|
||||
expandAffixAdjustWidth(NULL);
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -4588,6 +4982,9 @@ DecimalFormat::applyPatternInternally(const UnicodeString& pluralCount,
|
|||
UErrorCode& status) {
|
||||
applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
|
||||
expandAffixAdjustWidth(&pluralCount);
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -4598,6 +4995,9 @@ DecimalFormat::applyPatternInternally(const UnicodeString& pluralCount,
|
|||
*/
|
||||
void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
|
||||
NumberFormat::setMaximumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4607,6 +5007,9 @@ void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
|
|||
*/
|
||||
void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
|
||||
NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4616,6 +5019,9 @@ void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
|
|||
*/
|
||||
void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
|
||||
NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits));
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4625,6 +5031,9 @@ void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
|
|||
*/
|
||||
void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
|
||||
NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits));
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t DecimalFormat::getMinimumSignificantDigits() const {
|
||||
|
@ -4643,6 +5052,9 @@ void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
|
|||
int32_t max = _max(fMaxSignificantDigits, min);
|
||||
fMinSignificantDigits = min;
|
||||
fMaxSignificantDigits = max;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
|
||||
|
@ -4654,6 +5066,9 @@ void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
|
|||
int32_t min = _min(fMinSignificantDigits, max);
|
||||
fMinSignificantDigits = min;
|
||||
fMaxSignificantDigits = max;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
UBool DecimalFormat::areSignificantDigitsUsed() const {
|
||||
|
@ -4662,6 +5077,9 @@ UBool DecimalFormat::areSignificantDigitsUsed() const {
|
|||
|
||||
void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
|
||||
fUseSignificantDigits = useSignificantDigits;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DecimalFormat::setCurrencyInternally(const UChar* theCurrency,
|
||||
|
@ -4696,6 +5114,9 @@ void DecimalFormat::setCurrencyInternally(const UChar* theCurrency,
|
|||
}
|
||||
expandAffixes(NULL);
|
||||
}
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
|
||||
|
@ -4709,12 +5130,18 @@ void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
|
|||
}
|
||||
// set the currency after apply pattern to get the correct rounding/fraction
|
||||
setCurrencyInternally(theCurrency, ec);
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Deprecated variant with no UErrorCode parameter
|
||||
void DecimalFormat::setCurrency(const UChar* theCurrency) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
setCurrency(theCurrency, ec);
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
|
||||
|
@ -4853,7 +5280,14 @@ DecimalFormat::copyHashForAffixPattern(const Hashtable* source,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
|
||||
fParseAllInput = value;
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
handleChanged();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
DecimalFormat::copyHashForAffix(const Hashtable* source,
|
||||
|
|
|
@ -58,6 +58,10 @@
|
|||
//static const char I64_MIN_REP[] = "9223372036854775808";
|
||||
|
||||
|
||||
static const uint8_t DIGIT_HAVE_NONE=0;
|
||||
static const uint8_t DIGIT_HAVE_DOUBLE=1;
|
||||
static const uint8_t DIGIT_HAVE_INT64=2;
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -73,8 +77,7 @@ DigitList::DigitList()
|
|||
fDecNumber = fStorage.getAlias();
|
||||
uprv_decNumberZero(fDecNumber);
|
||||
|
||||
fDouble = 0.0;
|
||||
fHaveDouble = TRUE;
|
||||
internalSetDouble(0.0);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -116,8 +119,13 @@ DigitList::operator=(const DigitList& other)
|
|||
// Avoid potential races with that happening with other.fDouble
|
||||
// while we are doing the assignment.
|
||||
Mutex mutex;
|
||||
fDouble = other.fDouble;
|
||||
fHaveDouble = other.fHaveDouble;
|
||||
|
||||
if(other.fHave==kDouble) {
|
||||
fUnion.fDouble = other.fUnion.fDouble;
|
||||
} else if(other.fHave==kInt64) {
|
||||
fUnion.fInt64 = other.fUnion.fInt64;
|
||||
}
|
||||
fHave = other.fHave;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
|
@ -190,8 +198,7 @@ DigitList::clear()
|
|||
{
|
||||
uprv_decNumberZero(fDecNumber);
|
||||
uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
|
||||
fDouble = 0.0;
|
||||
fHaveDouble = TRUE;
|
||||
internalSetDouble(0.0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -278,7 +285,7 @@ DigitList::setPositive(UBool s) {
|
|||
} else {
|
||||
fDecNumber->bits |= DECNEG;
|
||||
}
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
// -------------------------------------
|
||||
|
||||
|
@ -293,7 +300,7 @@ DigitList::setDecimalAt(int32_t d) {
|
|||
adjustedDigits = 0;
|
||||
}
|
||||
fDecNumber->exponent = d - adjustedDigits;
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
@ -315,7 +322,7 @@ DigitList::setCount(int32_t c) {
|
|||
fDecNumber->lsu[0] = 0;
|
||||
}
|
||||
fDecNumber->digits = c;
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
@ -336,7 +343,7 @@ DigitList::setDigit(int32_t i, char v) {
|
|||
U_ASSERT(v>='0' && v<='9');
|
||||
v &= 0x0f;
|
||||
fDecNumber->lsu[count-i-1] = v;
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
char
|
||||
|
@ -390,7 +397,7 @@ DigitList::append(char digit)
|
|||
fDecNumber->exponent--;
|
||||
}
|
||||
}
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -409,8 +416,10 @@ DigitList::getDouble() const
|
|||
char decimalSeparator;
|
||||
{
|
||||
Mutex mutex;
|
||||
if (fHaveDouble) {
|
||||
return fDouble;
|
||||
if (fHave == kDouble) {
|
||||
return fUnion.fDouble;
|
||||
} else if(fHave == kInt64) {
|
||||
return (double)fUnion.fInt64;
|
||||
}
|
||||
decimalSeparator = gDecimal;
|
||||
}
|
||||
|
@ -438,7 +447,7 @@ DigitList::getDouble() const
|
|||
tDouble = std::numeric_limits<double>::max();
|
||||
}
|
||||
if (!isPositive()) {
|
||||
tDouble = -fDouble;
|
||||
tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
|
||||
}
|
||||
} else {
|
||||
MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
|
||||
|
@ -472,8 +481,7 @@ DigitList::getDouble() const
|
|||
{
|
||||
Mutex mutex;
|
||||
DigitList *nonConstThis = const_cast<DigitList *>(this);
|
||||
nonConstThis->fDouble = tDouble;
|
||||
nonConstThis->fHaveDouble = TRUE;
|
||||
nonConstThis->internalSetDouble(tDouble);
|
||||
gDecimal = decimalSeparator;
|
||||
}
|
||||
return tDouble;
|
||||
|
@ -511,6 +519,9 @@ int32_t DigitList::getLong() /*const*/
|
|||
* Return zero if the number cannot be represented.
|
||||
*/
|
||||
int64_t DigitList::getInt64() /*const*/ {
|
||||
if(fHave==kInt64) {
|
||||
return fUnion.fInt64;
|
||||
}
|
||||
// Truncate if non-integer.
|
||||
// Return 0 if out of range.
|
||||
// Range of in64_t is -9223372036854775808 to 9223372036854775807 (19 digits)
|
||||
|
@ -682,8 +693,7 @@ void
|
|||
DigitList::set(int32_t source)
|
||||
{
|
||||
set((int64_t)source);
|
||||
fDouble = source;
|
||||
fHaveDouble = TRUE;
|
||||
internalSetDouble(source);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -699,8 +709,18 @@ DigitList::set(int64_t source)
|
|||
U_ASSERT(uprv_strlen(str) < sizeof(str));
|
||||
|
||||
uprv_decNumberFromString(fDecNumber, str, &fContext);
|
||||
fDouble = (double)source;
|
||||
fHaveDouble = TRUE;
|
||||
internalSetDouble(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maximumDigits The maximum digits to be generated. If zero,
|
||||
* there is no maximum -- generate all digits.
|
||||
*/
|
||||
void
|
||||
DigitList::setInteger(int64_t source)
|
||||
{
|
||||
fDecNumber=NULL;
|
||||
internalSetInt64(source);
|
||||
}
|
||||
|
||||
|
||||
|
@ -738,7 +758,7 @@ DigitList::set(const StringPiece &source, UErrorCode &status) {
|
|||
if ((fContext.status & DEC_Conversion_syntax) != 0) {
|
||||
status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
|
||||
}
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -778,8 +798,7 @@ DigitList::set(double source)
|
|||
// Create a decNumber from the string.
|
||||
uprv_decNumberFromString(fDecNumber, rep, &fContext);
|
||||
uprv_decNumberTrim(fDecNumber);
|
||||
fDouble = source;
|
||||
fHaveDouble = TRUE;
|
||||
internalSetDouble(source);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -800,7 +819,7 @@ DigitList::mult(const DigitList &other, UErrorCode &status) {
|
|||
ensureCapacity(requiredDigits, status);
|
||||
}
|
||||
uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -817,7 +836,7 @@ DigitList::div(const DigitList &other, UErrorCode &status) {
|
|||
return;
|
||||
}
|
||||
uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -867,7 +886,7 @@ DigitList::round(int32_t maximumDigits)
|
|||
uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
|
||||
fContext.digits = savedDigits;
|
||||
uprv_decNumberTrim(fDecNumber);
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -884,7 +903,7 @@ DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
|
|||
|
||||
uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
|
||||
trim();
|
||||
fHaveDouble = FALSE;
|
||||
internalClear();
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -903,6 +922,12 @@ DigitList::isZero() const
|
|||
}
|
||||
|
||||
|
||||
|
||||
void * U_EXPORT2 DigitList::operator new(size_t size, void *stack, EStackMode mode) U_NO_THROW {
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif // #if !UCONFIG_NO_FORMATTING
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1997-2011, International Business Machines
|
||||
* Copyright (C) 1997-2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
@ -66,6 +66,8 @@ template class U_I18N_API MaybeStackHeaderAndArray<decNumber, char, DEFAULT_DIGI
|
|||
#endif
|
||||
|
||||
|
||||
enum EStackMode { kOnStack };
|
||||
|
||||
/**
|
||||
* Digit List is actually a Decimal Floating Point number.
|
||||
* The original implementation has been replaced by a thin wrapper onto a
|
||||
|
@ -247,6 +249,15 @@ public:
|
|||
*/
|
||||
void set(int64_t source);
|
||||
|
||||
/**
|
||||
* Utility routine to set the value of the digit list from an int64.
|
||||
* Does not set the decnumber unless requested later
|
||||
* 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
|
||||
*/
|
||||
void setInteger(int64_t source);
|
||||
|
||||
/**
|
||||
* Utility routine to set the value of the digit list from a decimal number
|
||||
* string.
|
||||
|
@ -383,12 +394,42 @@ private:
|
|||
* This is an optimization for the formatting implementation, which may
|
||||
* ask for the double value multiple times.
|
||||
*/
|
||||
double fDouble;
|
||||
UBool fHaveDouble;
|
||||
union DoubleOrInt64 {
|
||||
double fDouble;
|
||||
int64_t fInt64;
|
||||
} fUnion;
|
||||
enum EHave {
|
||||
kNone=0,
|
||||
kDouble,
|
||||
kInt64
|
||||
} fHave;
|
||||
|
||||
|
||||
|
||||
UBool shouldRoundUp(int32_t maximumDigits) const;
|
||||
|
||||
public:
|
||||
|
||||
using UMemory::operator new;
|
||||
|
||||
/**
|
||||
* Placement new for stack usage
|
||||
* @internal
|
||||
*/
|
||||
static void * U_EXPORT2 operator new(size_t size, void *onStack, EStackMode mode) U_NO_THROW;
|
||||
|
||||
private:
|
||||
inline void internalSetDouble(double d) {
|
||||
fHave = kDouble;
|
||||
fUnion.fDouble=d;
|
||||
}
|
||||
inline void internalSetInt64(int64_t d) {
|
||||
fHave = kInt64;
|
||||
fUnion.fInt64=d;
|
||||
}
|
||||
inline void internalClear() {
|
||||
fHave = kNone;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -36,6 +36,14 @@ U_NAMESPACE_BEGIN
|
|||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
|
||||
|
||||
struct FmtStackData {
|
||||
DigitList stackDecimalNum; // 128
|
||||
//CharString stackDecimalStr; // 64
|
||||
// -----
|
||||
// 192 total
|
||||
};
|
||||
|
||||
|
||||
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
|
||||
|
||||
// NOTE: As of 3.0, there are limitations to the UObject API. It does
|
||||
|
@ -253,7 +261,7 @@ Formattable::operator=(const Formattable& source)
|
|||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if (source.fDecimalNum != NULL) {
|
||||
fDecimalNum = new DigitList(*source.fDecimalNum);
|
||||
fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list
|
||||
}
|
||||
if (source.fDecimalStr != NULL) {
|
||||
fDecimalStr = new CharString(*source.fDecimalStr, status);
|
||||
|
@ -348,9 +356,20 @@ void Formattable::dispose()
|
|||
|
||||
fType = kLong;
|
||||
fValue.fInt64 = 0;
|
||||
|
||||
delete fDecimalStr;
|
||||
fDecimalStr = NULL;
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
FmtStackData *stackData = (FmtStackData*)fStackData;
|
||||
if(fDecimalNum != &(stackData->stackDecimalNum)) {
|
||||
delete fDecimalNum;
|
||||
} else {
|
||||
fDecimalNum->~DigitList(); // destruct, don't deallocate
|
||||
}
|
||||
#else
|
||||
delete fDecimalNum;
|
||||
#endif
|
||||
fDecimalNum = NULL;
|
||||
}
|
||||
|
||||
|
@ -695,7 +714,7 @@ StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
|
|||
// from parsing, or from the user setting a decimal number, fDecimalNum
|
||||
// would already be set.
|
||||
//
|
||||
fDecimalNum = new DigitList;
|
||||
fDecimalNum = new DigitList; // TODO: use internal digit list
|
||||
if (fDecimalNum == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return "";
|
||||
|
@ -729,13 +748,33 @@ StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
|
|||
}
|
||||
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
DigitList *
|
||||
Formattable::getInternalDigitList() {
|
||||
FmtStackData *stackData = (FmtStackData*)fStackData;
|
||||
if(fDecimalNum != &(stackData->stackDecimalNum)) {
|
||||
delete fDecimalNum;
|
||||
fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList();
|
||||
} else {
|
||||
fDecimalNum->clear();
|
||||
}
|
||||
return fDecimalNum;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------------------------------------
|
||||
void
|
||||
Formattable::adoptDigitList(DigitList *dl) {
|
||||
dispose();
|
||||
if(fDecimalNum==dl) {
|
||||
fDecimalNum = NULL; // don't delete
|
||||
}
|
||||
dispose();
|
||||
|
||||
fDecimalNum = dl;
|
||||
fDecimalNum = dl;
|
||||
|
||||
if(dl==NULL) { // allow adoptDigitList(NULL) to clear
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the value into the Union of simple type values.
|
||||
// Cannot use the set() functions because they would delete the fDecimalNum value,
|
||||
|
@ -765,7 +804,7 @@ Formattable::setDecimalNumber(const StringPiece &numberString, UErrorCode &statu
|
|||
// The decNumber library requires nul-terminated input. StringPiece input
|
||||
// is not guaranteed nul-terminated. Too bad.
|
||||
// CharString automatically adds the nul.
|
||||
DigitList *dnum = new DigitList();
|
||||
DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList
|
||||
if (dnum == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
#ifdef FMT_DEBUG
|
||||
#include <stdio.h>
|
||||
static void debugout(UnicodeString s) {
|
||||
static inline void debugout(UnicodeString s) {
|
||||
char buf[2000];
|
||||
s.extract((int32_t) 0, s.length(), buf);
|
||||
printf("%s", buf);
|
||||
|
|
|
@ -39,6 +39,14 @@
|
|||
#include "unicode/stringpiece.h"
|
||||
#include "unicode/curramt.h"
|
||||
|
||||
/**
|
||||
* \def UNUM_DECIMFORMAT_INTERNAL_SIZE
|
||||
* @internal
|
||||
*/
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
#define UNUM_DECIMALFORMAT_INTERNAL_SIZE 16
|
||||
#endif
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class DigitList;
|
||||
|
@ -747,6 +755,15 @@ public:
|
|||
DecimalFormatSymbols* symbolsToAdopt,
|
||||
UNumberFormatStyle style,
|
||||
UErrorCode& status);
|
||||
|
||||
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void setParseAllInput(UNumberFormatAttributeValue value);
|
||||
#endif
|
||||
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
/**
|
||||
|
@ -1864,7 +1881,7 @@ private:
|
|||
* Initialize all fields of a new DecimalFormatter.
|
||||
* Common code for use by constructors.
|
||||
*/
|
||||
void init();
|
||||
void init(UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Do real work of constructing a new DecimalFormat.
|
||||
|
@ -2261,6 +2278,11 @@ private:
|
|||
// Information needed for DecimalFormat to format/parse currency plural.
|
||||
CurrencyPluralInfo* fCurrencyPluralInfo;
|
||||
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
UNumberFormatAttributeValue fParseAllInput;
|
||||
#endif
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
@ -2293,6 +2315,21 @@ protected:
|
|||
* @stable ICU 2.8
|
||||
*/
|
||||
static const int32_t kMaxScientificIntegerDigits;
|
||||
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
private:
|
||||
/**
|
||||
* Internal state.
|
||||
* @internal
|
||||
*/
|
||||
uint8_t fReserved[UNUM_DECIMALFORMAT_INTERNAL_SIZE];
|
||||
|
||||
|
||||
/**
|
||||
* Called whenever any state changes. Recomputes whether fastpath is OK to use.
|
||||
*/
|
||||
void handleChanged();
|
||||
#endif
|
||||
};
|
||||
|
||||
inline UnicodeString&
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 1997-2011, International Business Machines
|
||||
* Copyright (C) 1997-2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
********************************************************************************
|
||||
*
|
||||
|
@ -605,6 +605,14 @@ public:
|
|||
*/
|
||||
DigitList *getDigitList() const { return fDecimalNum;}
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
DigitList *getInternalDigitList();
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Adopt, and set value from, a DigitList
|
||||
* Internal Function, do not use.
|
||||
|
@ -641,8 +649,13 @@ private:
|
|||
} fValue;
|
||||
|
||||
CharString *fDecimalStr;
|
||||
|
||||
DigitList *fDecimalNum;
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
char fStackData[128]; // must be big enough for DigitList
|
||||
#endif
|
||||
|
||||
Type fType;
|
||||
UnicodeString fBogus; // Bogus string when it's needed.
|
||||
};
|
||||
|
|
|
@ -715,6 +715,20 @@ unum_getAvailable(int32_t localeIndex);
|
|||
U_STABLE int32_t U_EXPORT2
|
||||
unum_countAvailable(void);
|
||||
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
typedef enum UNumberFormatAttributeValue {
|
||||
/** @internal */
|
||||
UNUM_NO = 0,
|
||||
/** @internal */
|
||||
UNUM_YES = 1,
|
||||
/** @internal */
|
||||
UNUM_MAYBE = 2
|
||||
} UNumberFormatAttributeValue;
|
||||
#endif
|
||||
|
||||
/** The possible UNumberFormat numeric attributes @stable ICU 2.0 */
|
||||
typedef enum UNumberFormatAttribute {
|
||||
/** Parse integers only */
|
||||
|
@ -762,6 +776,14 @@ typedef enum UNumberFormatAttribute {
|
|||
* @stable ICU 3.0
|
||||
*/
|
||||
UNUM_LENIENT_PARSE
|
||||
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
/** Consume all input. (may use fastpath). Set to UNUM_YES (require fastpath), UNUM_NO (skip fastpath), or UNUM_MAYBE (heuristic).
|
||||
* @internal
|
||||
*/
|
||||
,UNUM_PARSE_ALL_INPUT
|
||||
#endif
|
||||
|
||||
} UNumberFormatAttribute;
|
||||
|
||||
/**
|
||||
|
|
|
@ -626,6 +626,12 @@ unum_setAttribute( UNumberFormat* fmt,
|
|||
df->setSecondaryGroupingSize(newValue);
|
||||
break;
|
||||
|
||||
#if UCONFIG_HAVE_PARSEALLINPUT
|
||||
case UNUM_PARSE_ALL_INPUT:
|
||||
df->setParseAllInput((UNumberFormatAttributeValue)newValue);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
/* Shouldn't get here anyway */
|
||||
break;
|
||||
|
|
|
@ -1888,32 +1888,32 @@ static void TestTextAttributeCrash(void) {
|
|||
unum_close(nf);
|
||||
}
|
||||
|
||||
static void TestNBSPPatternRtNum(const char *testcase, UNumberFormat *nf, double myNumber) {
|
||||
static void TestNBSPPatternRtNum(const char *testcase, int line, UNumberFormat *nf, double myNumber) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UChar myString[20];
|
||||
char tmpbuf[200];
|
||||
double aNumber = -1.0;
|
||||
unum_formatDouble(nf, myNumber, myString, 20, NULL, &status);
|
||||
log_verbose("%s: formatted %.2f into %s\n", testcase, myNumber, u_austrcpy(tmpbuf, myString));
|
||||
log_verbose("%s:%d: formatted %.2f into %s\n", testcase, line, myNumber, u_austrcpy(tmpbuf, myString));
|
||||
if(U_FAILURE(status)) {
|
||||
log_err("%s: failed format of %.2g with %s\n", testcase, myNumber, u_errorName(status));
|
||||
log_err("%s:%d: failed format of %.2g with %s\n", testcase, line, myNumber, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
aNumber = unum_parse(nf, myString, -1, NULL, &status);
|
||||
if(U_FAILURE(status)) {
|
||||
log_err("%s: failed parse with %s\n", testcase, u_errorName(status));
|
||||
log_err("%s:%d: failed parse with %s\n", testcase, line, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
if(uprv_fabs(aNumber-myNumber)>.001) {
|
||||
log_err("FAIL: %s: formatted %.2f, parsed into %.2f\n", testcase, myNumber, aNumber);
|
||||
log_err("FAIL: %s:%d formatted %.2f, parsed into %.2f\n", testcase, line, myNumber, aNumber);
|
||||
} else {
|
||||
log_verbose("PASS: %s: formatted %.2f, parsed into %.2f\n", testcase, myNumber, aNumber);
|
||||
log_verbose("PASS: %s:%d formatted %.2f, parsed into %.2f\n", testcase, line, myNumber, aNumber);
|
||||
}
|
||||
}
|
||||
|
||||
static void TestNBSPPatternRT(const char *testcase, UNumberFormat *nf) {
|
||||
TestNBSPPatternRtNum(testcase, nf, 12345.);
|
||||
TestNBSPPatternRtNum(testcase, nf, -12345.);
|
||||
TestNBSPPatternRtNum(testcase, __LINE__, nf, 12345.);
|
||||
TestNBSPPatternRtNum(testcase, __LINE__, nf, -12345.);
|
||||
}
|
||||
|
||||
static void TestNBSPInPattern(void) {
|
||||
|
@ -1925,7 +1925,7 @@ static void TestNBSPInPattern(void) {
|
|||
testcase="ar_AE UNUM_CURRENCY";
|
||||
nf = unum_open(UNUM_CURRENCY, NULL, -1, "ar_AE", NULL, &status);
|
||||
if(U_FAILURE(status) || nf == NULL) {
|
||||
log_data_err("%s: unum_open failed with %s (Are you missing data?)\n", testcase, u_errorName(status));
|
||||
log_data_err("%s:%d: %s: unum_open failed with %s (Are you missing data?)\n", __FILE__, __LINE__, testcase, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
TestNBSPPatternRT(testcase, nf);
|
||||
|
|
|
@ -118,6 +118,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
|
|||
CASE(52,TestAvailableNumberingSystems);
|
||||
CASE(53,TestRoundingPattern);
|
||||
CASE(54,Test9087);
|
||||
CASE(55,TestFormatFastpaths);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
@ -6571,4 +6572,21 @@ NumberFormatTest::Test9087(void)
|
|||
|
||||
unum_close(fmt);
|
||||
}
|
||||
|
||||
#include "dcfmtimp.h"
|
||||
|
||||
void NumberFormatTest::TestFormatFastpaths() {
|
||||
#if UCONFIG_FORMAT_FASTPATHS_49
|
||||
logln("Sizeof DecimalFormat = %d, Sizeof DecimalFormatInternal=%d, UNUM_DECIMALFORMAT_INTERNAL_SIZE=%d\n",
|
||||
sizeof(DecimalFormat), sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE);
|
||||
if(UNUM_DECIMALFORMAT_INTERNAL_SIZE < sizeof(DecimalFormatInternal)) {
|
||||
errln("Error: sizeof(DecimalFormatInternal)=%d but UNUM_DECIMALFORMAT_INTERNAL_SIZE is only %d. Increase the #define?\n", sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE);
|
||||
} else if(UNUM_DECIMALFORMAT_INTERNAL_SIZE > (sizeof(DecimalFormatInternal)+16)) {
|
||||
infoln("Note: sizeof(DecimalFormatInternal)=%d but UNUM_DECIMALFORMAT_INTERNAL_SIZE is %d. Decrease the #define? sizeof(DecimalFormat)=%d\n", sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE, sizeof(DecimalFormat));
|
||||
}
|
||||
#else
|
||||
infoln("NOTE: UCONFIG_FORMAT_FASTPATHS not set, test skipped.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -156,6 +156,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
|
|||
void TestExplicitParents();
|
||||
void TestAvailableNumberingSystems();
|
||||
void Test9087();
|
||||
void TestFormatFastpaths();
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "unicode/utimer.h"
|
||||
#include "udbgutil.h"
|
||||
#include "unicode/ustring.h"
|
||||
|
||||
#include "unicode/decimfmt.h"
|
||||
void runTests(void);
|
||||
|
||||
#ifndef ITERATIONS
|
||||
|
@ -187,7 +187,7 @@ public:
|
|||
}
|
||||
protected:
|
||||
virtual UNumberFormat* initFmt() {
|
||||
return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), 1, "en_US", 0, &setupStatus);
|
||||
return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, "en_US", 0, &setupStatus);
|
||||
}
|
||||
virtual const char *getClassName() {
|
||||
return "NumTest";
|
||||
|
@ -287,7 +287,7 @@ public:
|
|||
}
|
||||
protected:
|
||||
virtual UNumberFormat* initFmt() {
|
||||
return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), 1, "en_US", 0, &setupStatus);
|
||||
return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, "en_US", 0, &setupStatus);
|
||||
}
|
||||
virtual const char *getClassName() {
|
||||
return "NumFmtTest";
|
||||
|
@ -364,7 +364,7 @@ public:
|
|||
}
|
||||
protected:
|
||||
virtual UNumberFormat* initFmt() {
|
||||
return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), 1, "en_US", 0, &setupStatus);
|
||||
return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, "en_US", 0, &setupStatus);
|
||||
}
|
||||
virtual const char *getClassName() {
|
||||
return "NumFmtInt64Test";
|
||||
|
@ -418,6 +418,88 @@ public:
|
|||
|
||||
#define DO_NumFmtInt64Test(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
|
||||
|
||||
|
||||
class NumFmtStringPieceTest : public HowExpensiveTest {
|
||||
private:
|
||||
const StringPiece &fExpect;
|
||||
UNumberFormat *fFmt;
|
||||
UnicodeString fPat;
|
||||
UnicodeString fString;
|
||||
const UChar *fStr;
|
||||
int32_t fLen;
|
||||
const char *fFile;
|
||||
int fLine;
|
||||
const char *fCPat;
|
||||
const char *fCStr;
|
||||
char name[100];
|
||||
public:
|
||||
virtual const char *getName() {
|
||||
if(name[0]==0) {
|
||||
sprintf(name,"%s:p=|%s|,str=|%s|,sp=|%s|",getClassName(),fCPat,fCStr, fExpect.data());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
protected:
|
||||
virtual UNumberFormat* initFmt() {
|
||||
DecimalFormat *d = new DecimalFormat(setupStatus);
|
||||
UParseError pe;
|
||||
d->applyPattern(fPat, pe, setupStatus);
|
||||
return (UNumberFormat*) d;
|
||||
}
|
||||
virtual const char *getClassName() {
|
||||
return "NumFmtStringPieceTest";
|
||||
}
|
||||
public:
|
||||
NumFmtStringPieceTest(const char *pat, const char *num, const StringPiece& expect, const char *FILE, int LINE)
|
||||
: HowExpensiveTest("(n/a)",FILE, LINE),
|
||||
fExpect(expect),
|
||||
fFmt(0),
|
||||
fPat(pat, -1, US_INV),
|
||||
fString(num,-1,US_INV),
|
||||
fStr(fString.getTerminatedBuffer()),
|
||||
fLen(u_strlen(fStr)),
|
||||
fFile(FILE),
|
||||
fLine(LINE),
|
||||
fCPat(pat),
|
||||
fCStr(num)
|
||||
{
|
||||
name[0]=0;
|
||||
}
|
||||
void warmup() {
|
||||
fFmt = initFmt();
|
||||
UnicodeString buf;
|
||||
if(U_SUCCESS(setupStatus)) {
|
||||
buf.remove();
|
||||
((const DecimalFormat*)fFmt)->format(fExpect, buf, NULL, setupStatus);
|
||||
if(!U_SUCCESS(setupStatus)
|
||||
|| fString!=buf
|
||||
) {
|
||||
char strBuf[200];
|
||||
u_strToUTF8(strBuf,200,NULL,buf.getTerminatedBuffer(),buf.length()+1,&setupStatus);
|
||||
printf("%s:%d: warmup() %s got %s (len %d) expected %s (len %d), err %s\n",
|
||||
fFile,fLine,getName(),strBuf,buf.length(),fCStr,fLen, u_errorName(setupStatus));
|
||||
setupStatus = U_INTERNAL_PROGRAM_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t run() {
|
||||
int32_t trial;
|
||||
int i;
|
||||
UnicodeString buf;
|
||||
if(U_SUCCESS(setupStatus)) {
|
||||
for(i=0;i<U_LOTS_OF_TIMES;i++){
|
||||
buf.remove();
|
||||
((const DecimalFormat*)fFmt)->format(fExpect, buf, NULL, setupStatus);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
virtual ~NumFmtStringPieceTest(){}
|
||||
};
|
||||
|
||||
#define DO_NumFmtStringPieceTest(p,n,x) { NumFmtStringPieceTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
|
||||
|
||||
// TODO: move, scope.
|
||||
static UChar pattern[] = { 0x23 }; // '#'
|
||||
static UChar strdot[] = { '2', '.', '0', 0 };
|
||||
|
@ -489,6 +571,23 @@ void runTests() {
|
|||
#ifndef SKIP_NUMFORMAT_TESTS
|
||||
// format tests
|
||||
{
|
||||
|
||||
DO_NumFmtInt64Test("0000","0001",1);
|
||||
DO_NumFmtInt64Test("0000","0000",0);
|
||||
StringPiece sp3456("3456");
|
||||
DO_NumFmtStringPieceTest("0000","3456",sp3456);
|
||||
DO_NumFmtStringPieceTest("#","3456",sp3456);
|
||||
StringPiece sp3("3");
|
||||
DO_NumFmtStringPieceTest("0000","0003",sp3);
|
||||
DO_NumFmtStringPieceTest("#","3",sp3);
|
||||
StringPiece spn3("-3");
|
||||
DO_NumFmtStringPieceTest("0000","-0003",spn3);
|
||||
DO_NumFmtStringPieceTest("#","-3",spn3);
|
||||
StringPiece spPI("123.456");
|
||||
DO_NumFmtStringPieceTest("#.0000","123.4560",spPI);
|
||||
DO_NumFmtStringPieceTest("#.00","123.46",spPI);
|
||||
|
||||
#if 1
|
||||
DO_NumFmtTest("#","0",0.0);
|
||||
DO_NumFmtTest("#","12345",12345);
|
||||
DO_NumFmtTest("#","-2",-2);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "putilimp.h"
|
||||
#include "unicode/ulocdata.h"
|
||||
#include "unicode/ucnv.h"
|
||||
|
||||
/*
|
||||
To add a new enum type
|
||||
(For example: UShoeSize with values USHOE_WIDE=0, USHOE_REGULAR, USHOE_NARROW, USHOE_COUNT)
|
||||
|
@ -509,7 +510,9 @@ static USystemParams systemParams[] = {
|
|||
#if defined (CYGWINMSVC)
|
||||
{ "build.cygwinmsvc", paramInteger, "b", 1},
|
||||
#endif
|
||||
|
||||
{ "uconfig.internal_digitlist", paramInteger, "b", UCONFIG_INTERNAL_DIGITLIST},
|
||||
{ "uconfig.have_parseallinput", paramInteger, "b", UCONFIG_HAVE_PARSEALLINPUT},
|
||||
{ "uconfig.format_fastpaths_49",paramInteger, "b", UCONFIG_FORMAT_FASTPATHS_49},
|
||||
|
||||
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue