ICU-551.24.tar.gz
[apple/icu.git] / icuSources / i18n / digitlst.cpp
index b885a17cb212075d045fff5a76ad5322f17168ec..51738bec027d5e98dfcb5cc9ecb4e70182858184 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 1997-2012, International Business Machines
+*   Copyright (C) 1997-2015, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *
@@ -54,8 +54,8 @@
 
 
 /* Only for 32 bit numbers. Ignore the negative sign. */
-static const char LONG_MIN_REP[] = "2147483648";
-static const char I64_MIN_REP[] = "9223372036854775808";
+//static const char LONG_MIN_REP[] = "2147483648";
+//static const char I64_MIN_REP[] = "9223372036854775808";
 
 
 U_NAMESPACE_BEGIN
@@ -73,8 +73,7 @@ DigitList::DigitList()
     fDecNumber = fStorage.getAlias();
     uprv_decNumberZero(fDecNumber);
 
-    fDouble = 0.0;
-    fHaveDouble = TRUE;
+    internalSetDouble(0.0);
 }
 
 // -------------------------------------
@@ -116,8 +115,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 +194,7 @@ DigitList::clear()
 {
     uprv_decNumberZero(fDecNumber);
     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
-    fDouble = 0.0;
-    fHaveDouble = TRUE;
+    internalSetDouble(0.0);
 }
 
 
@@ -278,7 +281,7 @@ DigitList::setPositive(UBool s) {
     } else {
         fDecNumber->bits |= DECNEG;
     }
-    fHaveDouble = FALSE;
+    internalClear();
 }
 // -------------------------------------
 
@@ -293,7 +296,7 @@ DigitList::setDecimalAt(int32_t d) {
         adjustedDigits = 0;
     }
     fDecNumber->exponent = d - adjustedDigits;
-    fHaveDouble = FALSE;
+    internalClear();
 }
 
 int32_t  
@@ -315,7 +318,7 @@ DigitList::setCount(int32_t c)  {
         fDecNumber->lsu[0] = 0;
     }
     fDecNumber->digits = c;
-    fHaveDouble = FALSE;
+    internalClear();
 }
 
 int32_t  
@@ -336,7 +339,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 +393,7 @@ DigitList::append(char digit)
             fDecNumber->exponent--;
         }
     }
-    fHaveDouble = FALSE;
+    internalClear();
 }
 
 // -------------------------------------
@@ -409,8 +412,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 +443,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;
@@ -453,27 +458,26 @@ DigitList::getDouble() const
             DigitList numToConvert(*this);
             numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
             numToConvert.round(MAX_DBL_DIGITS+3);
-            uprv_decNumberToString(numToConvert.fDecNumber, s);
+            uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias());
             // TODO:  how many extra digits should be included for an accurate conversion?
         } else {
-            uprv_decNumberToString(this->fDecNumber, s);
+            uprv_decNumberToString(this->fDecNumber, s.getAlias());
         }
         U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
         
         if (decimalSeparator != '.') {
-            char *decimalPt = strchr(s, '.');
+            char *decimalPt = strchr(s.getAlias(), '.');
             if (decimalPt != NULL) {
                 *decimalPt = decimalSeparator;
             }
         }
         char *end = NULL;
-        tDouble = uprv_strtod(s, &end);
+        tDouble = uprv_strtod(s.getAlias(), &end);
     }
     {
         Mutex mutex;
         DigitList *nonConstThis = const_cast<DigitList *>(this);
-        nonConstThis->fDouble = tDouble;
-        nonConstThis->fHaveDouble = TRUE;
+        nonConstThis->internalSetDouble(tDouble);
         gDecimal = decimalSeparator;
     }
     return tDouble;
@@ -511,6 +515,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,14 +689,12 @@ void
 DigitList::set(int32_t source)
 {
     set((int64_t)source);
-    fDouble = source;
-    fHaveDouble = TRUE;
+    internalSetDouble(source);
 }
 
 // -------------------------------------
 /**
- * @param maximumDigits The maximum digits to be generated.  If zero,
- * there is no maximum -- generate all digits.
+ * Set an int64, via decnumber
  */
 void
 DigitList::set(int64_t source)
@@ -699,8 +704,17 @@ DigitList::set(int64_t source)
     U_ASSERT(uprv_strlen(str) < sizeof(str));
 
     uprv_decNumberFromString(fDecNumber, str, &fContext);
-    fDouble = (double)source;
-    fHaveDouble = TRUE;
+    internalSetDouble(static_cast<double>(source));
+}
+
+/**
+ * Set an int64, with no decnumber
+ */
+void
+DigitList::setInteger(int64_t source)
+{
+  fDecNumber=NULL;
+  internalSetInt64(source);
 }
 
 
@@ -714,31 +728,58 @@ DigitList::set(int64_t source)
  * be acceptable for a public API.
  */
 void
-DigitList::set(const StringPiece &source, UErrorCode &status) {
+DigitList::set(const StringPiece &source, UErrorCode &status, uint32_t /*fastpathBits*/) {
     if (U_FAILURE(status)) {
         return;
     }
 
-    // Figure out a max number of digits to use during the conversion, and
-    // resize the number up if necessary.
-    int32_t numDigits = source.length();
-    if (numDigits > fContext.digits) {
+#if 0    
+    if(fastpathBits==(kFastpathOk|kNoDecimal)) {
+      int32_t size = source.size();
+      const char *data = source.data();
+      int64_t r = 0;
+      int64_t m = 1;
+      // fast parse
+      while(size>0) {
+        char ch = data[--size];
+        if(ch=='+') {
+          break;
+        } else if(ch=='-') {
+          r = -r;
+          break;
+        } else {
+          int64_t d = ch-'0';
+          //printf("CH[%d]=%c, %d, *=%d\n", size,ch, (int)d, (int)m);
+          r+=(d)*m;
+          m *= 10;
+        }
+      }
+      //printf("R=%d\n", r);
+      set(r);
+    } else
+#endif
+        {
+      // Figure out a max number of digits to use during the conversion, and
+      // resize the number up if necessary.
+      int32_t numDigits = source.length();
+      if (numDigits > fContext.digits) {
         // fContext.digits == fStorage.getCapacity()
         decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
         if (t == NULL) {
-            status = U_MEMORY_ALLOCATION_ERROR;
-            return;
+          status = U_MEMORY_ALLOCATION_ERROR;
+          return;
         }
         fDecNumber = t;
         fContext.digits = numDigits;
-    }
+      }
 
-    fContext.status = 0;
-    uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
-    if ((fContext.status & DEC_Conversion_syntax) != 0) {
+      fContext.status = 0;
+      uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
+      if ((fContext.status & DEC_Conversion_syntax) != 0) {
         status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
+      }
     }
-    fHaveDouble = FALSE;
+    internalClear();
 }   
 
 /**
@@ -778,8 +819,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 +840,7 @@ DigitList::mult(const DigitList &other, UErrorCode &status) {
         ensureCapacity(requiredDigits, status);
     }
     uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
-    fHaveDouble = FALSE;
+    internalClear();
 }
 
 // -------------------------------------
@@ -817,7 +857,7 @@ DigitList::div(const DigitList &other, UErrorCode &status) {
         return;
     }
     uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
-    fHaveDouble = FALSE;
+    internalClear();
 }
 
 // -------------------------------------
@@ -867,7 +907,7 @@ DigitList::round(int32_t maximumDigits)
     uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
     fContext.digits = savedDigits;
     uprv_decNumberTrim(fDecNumber);
-    fHaveDouble = FALSE;
+    internalClear();
 }
 
 
@@ -884,7 +924,7 @@ DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
     
     uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
     trim();
-    fHaveDouble = FALSE;
+    internalClear();
 }
 
 // -------------------------------------
@@ -902,7 +942,6 @@ DigitList::isZero() const
     return decNumberIsZero(fDecNumber);
 }
 
-
 U_NAMESPACE_END
 #endif // #if !UCONFIG_NO_FORMATTING