]> granicus.if.org Git - icu/commitdiff
ICU-9258 merge from branches, performance improvements
authorSteven R. Loomis <srl@icu-project.org>
Wed, 30 May 2012 00:41:57 +0000 (00:41 +0000)
committerSteven R. Loomis <srl@icu-project.org>
Wed, 30 May 2012 00:41:57 +0000 (00:41 +0000)
X-SVN-Rev: 31881

18 files changed:
icu4c/source/common/cmemory.c
icu4c/source/common/cmemory.h
icu4c/source/common/unicode/uconfig.h
icu4c/source/i18n/dcfmtimp.h [new file with mode: 0644]
icu4c/source/i18n/decimfmt.cpp
icu4c/source/i18n/digitlst.cpp
icu4c/source/i18n/digitlst.h
icu4c/source/i18n/fmtable.cpp
icu4c/source/i18n/numfmt.cpp
icu4c/source/i18n/unicode/decimfmt.h
icu4c/source/i18n/unicode/fmtable.h
icu4c/source/i18n/unicode/unum.h
icu4c/source/i18n/unum.cpp
icu4c/source/test/cintltst/cnumtst.c
icu4c/source/test/intltest/numfmtst.cpp
icu4c/source/test/intltest/numfmtst.h
icu4c/source/test/perf/howExpensiveIs/howExpensiveIs.cpp
icu4c/source/tools/toolutil/udbgutil.cpp

index b891607703807dbc89a8779349ecf1485dd8fbd9..d0839215207878f04ce97d7cd02ea23588f7b592 100644 (file)
@@ -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);
index c48e7a4c3ef8a1fba272ecda8c73c4b9c800ea13..8feb7009c213be28fc2a7ca53fbf4d93bc987082 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1997-2011, International Business Machines
+*   Copyright (C) 1997-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
 #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;
index f39eede23f1b1c6127645e1e9c9ff9663d37c518..ab03755c2a9d2a8700aa992fb0a96cc3ecd51260 100644 (file)
 #   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
diff --git a/icu4c/source/i18n/dcfmtimp.h b/icu4c/source/i18n/dcfmtimp.h
new file mode 100644 (file)
index 0000000..6bc2c0f
--- /dev/null
@@ -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
index ae68388cf1712f3651bef8b73eb1f8277109c1e6..ff15a14765af0f073c9497e0c9c5d55dc38e4825 100644 (file)
 #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,
index 31361be5aa931d44e3327f15232be8c4b8da4d60..5d7eb92e93f5e266431f1de0407ae8c8a027aebb 100644 (file)
 //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
 
index c4e1d88e07bf753749ceebfb4bb376d9d24175b3..7234afed05e4e7315b22c3514b4147f6e5106c6e 100644 (file)
@@ -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;
+    }
 };
 
 
index b28bf6a3f2b27d4fb38f16667689c17250fff993..947649b348f70c0cec82a62e8a5050f0c94fcdac 100644 (file)
@@ -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;
index df768aef139a027ba68408d543fcc7a2287008bd..161559ace001afd861d5960342932dbd73d99f83 100644 (file)
@@ -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);
index 04cef4290363f5b077a279a9695c9be2cc873588..f483cffed2e278d042e1698dd7803982eeeaaa78 100644 (file)
 #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&
index 641236fed4962522525df4757c7184430bc8ff52..694e2793256669d980dc9398a041ea9707698ed3 100644 (file)
@@ -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.
 };
index 3f9f291aac23546ec269c36d3c143683a1574eed..d26719797f9b07dc4e7c12f330f250a7adef212f 100644 (file)
@@ -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;
 
 /**
index 4fc3f5d4b8c4d138d542639dcb32f756ab3e517d..be519d4ef49d8edbee98bba42eca06bbe4a8c5d0 100644 (file)
@@ -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;
index 25c53a21715d464e862b8c686f74628d364c378c..81ba501d836a29d5822affbb5824f437694416aa 100644 (file)
@@ -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);
index 85028207da74a5f376c1fe43ec70d35d7ff85f93..734465c6f3c703918f8afc8f0634787ca02d71d1 100644 (file)
@@ -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 */
index da44791fb19b36afea3c892d228f6a5a07cbdab1..b95989bfe8632ace485e21d66769d15c968a0e3a 100644 (file)
@@ -156,6 +156,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
     void TestExplicitParents();
     void TestAvailableNumberingSystems();
     void Test9087();
+    void TestFormatFastpaths();
 
 
  private:
index 8f50d816db347d7cb220af36792f0e8ead363fed..fcfd27b3f64857801abaa3d8131f8f4c7a05c689 100644 (file)
@@ -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);
index 385a88b137e06b01481bd98142ad9eee26f7936a..d9f7869a3d591441d8cd47ac3fffd01eca4deb20 100644 (file)
@@ -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},
 
 
 };