• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 **********************************************************************
5 *   Copyright (C) 1997-2015, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 **********************************************************************
8 *
9 * File DIGITLST.CPP
10 *
11 * Modification History:
12 *
13 *   Date        Name        Description
14 *   03/21/97    clhuang     Converted from java.
15 *   03/21/97    clhuang     Implemented with new APIs.
16 *   03/27/97    helena      Updated to pass the simple test after code review.
17 *   03/31/97    aliu        Moved isLONG_MIN to here, and fixed it.
18 *   04/15/97    aliu        Changed MAX_COUNT to DBL_DIG.  Changed Digit to char.
19 *                           Reworked representation by replacing fDecimalAt
20 *                           with fExponent.
21 *   04/16/97    aliu        Rewrote set() and getDouble() to use sprintf/atof
22 *                           to do digit conversion.
23 *   09/09/97    aliu        Modified for exponential notation support.
24 *   08/02/98    stephen     Added nearest/even rounding
25 *                            Fixed bug in fitsIntoLong
26 ******************************************************************************
27 */
28 
29 #if defined(__CYGWIN__) && !defined(_GNU_SOURCE)
30 #define _GNU_SOURCE
31 #endif
32 
33 #include "digitlst.h"
34 
35 #if !UCONFIG_NO_FORMATTING
36 
37 #include "unicode/putil.h"
38 #include "charstr.h"
39 #include "cmemory.h"
40 #include "cstring.h"
41 #include "mutex.h"
42 #include "putilimp.h"
43 #include "uassert.h"
44 #include "digitinterval.h"
45 #include "ucln_in.h"
46 #include "umutex.h"
47 #include <stdlib.h>
48 #include <limits.h>
49 #include <string.h>
50 #include <stdio.h>
51 #include <limits>
52 
53 #if !defined(U_USE_STRTOD_L)
54 # if U_PLATFORM_USES_ONLY_WIN32_API
55 #   define U_USE_STRTOD_L 1
56 # elif defined(U_HAVE_STRTOD_L)
57 #   define U_USE_STRTOD_L U_HAVE_STRTOD_L
58 # else
59 #   define U_USE_STRTOD_L 0
60 # endif
61 #endif
62 
63 #if U_USE_STRTOD_L && !U_PLATFORM_USES_ONLY_WIN32_API
64 # if U_PLATFORM == U_PF_CYGWIN
65 #   include <locale.h>
66 # else
67 #   include <xlocale.h>
68 # endif
69 #endif
70 
71 // ***************************************************************************
72 // class DigitList
73 //    A wrapper onto decNumber.
74 //    Used to be standalone.
75 // ***************************************************************************
76 
77 /**
78  * This is the zero digit.  The base for the digits returned by getDigit()
79  * Note that it is the platform invariant digit, and is not Unicode.
80  */
81 #define kZero '0'
82 
83 
84 /* Only for 32 bit numbers. Ignore the negative sign. */
85 //static const char LONG_MIN_REP[] = "2147483648";
86 //static const char I64_MIN_REP[] = "9223372036854775808";
87 
88 
89 U_NAMESPACE_BEGIN
90 
91 // -------------------------------------
92 // default constructor
93 
DigitList()94 DigitList::DigitList()
95 {
96     uprv_decContextDefault(&fContext, DEC_INIT_BASE);
97     fContext.traps  = 0;
98     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
99     fContext.digits = fStorage.getCapacity();
100 
101     fDecNumber = fStorage.getAlias();
102     uprv_decNumberZero(fDecNumber);
103 
104     internalSetDouble(0.0);
105 }
106 
107 // -------------------------------------
108 
~DigitList()109 DigitList::~DigitList()
110 {
111 }
112 
113 // -------------------------------------
114 // copy constructor
115 
DigitList(const DigitList & other)116 DigitList::DigitList(const DigitList &other)
117 {
118     fDecNumber = fStorage.getAlias();
119     *this = other;
120 }
121 
122 
123 // -------------------------------------
124 // assignment operator
125 
126 DigitList&
operator =(const DigitList & other)127 DigitList::operator=(const DigitList& other)
128 {
129     if (this != &other)
130     {
131         uprv_memcpy(&fContext, &other.fContext, sizeof(decContext));
132 
133         if (other.fStorage.getCapacity() > fStorage.getCapacity()) {
134             fDecNumber = fStorage.resize(other.fStorage.getCapacity());
135         }
136         // Always reset the fContext.digits, even if fDecNumber was not reallocated,
137         // because above we copied fContext from other.fContext.
138         fContext.digits = fStorage.getCapacity();
139         uprv_decNumberCopy(fDecNumber, other.fDecNumber);
140 
141         {
142             // fDouble is lazily created and cached.
143             // Avoid potential races with that happening with other.fDouble
144             // while we are doing the assignment.
145             Mutex mutex;
146 
147             if(other.fHave==kDouble) {
148                 fUnion.fDouble = other.fUnion.fDouble;
149             }
150             fHave = other.fHave;
151         }
152     }
153     return *this;
154 }
155 
156 // -------------------------------------
157 //    operator ==  (does not exactly match the old DigitList function)
158 
159 UBool
operator ==(const DigitList & that) const160 DigitList::operator==(const DigitList& that) const
161 {
162     if (this == &that) {
163         return TRUE;
164     }
165     decNumber n;  // Has space for only a none digit value.
166     decContext c;
167     uprv_decContextDefault(&c, DEC_INIT_BASE);
168     c.digits = 1;
169     c.traps = 0;
170 
171     uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c);
172     UBool result = decNumberIsZero(&n);
173     return result;
174 }
175 
176 // -------------------------------------
177 //      comparison function.   Returns
178 //         Not Comparable :  -2
179 //                      < :  -1
180 //                     == :   0
181 //                      > :  +1
compare(const DigitList & other)182 int32_t DigitList::compare(const DigitList &other) {
183     decNumber   result;
184     int32_t     savedDigits = fContext.digits;
185     fContext.digits = 1;
186     uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
187     fContext.digits = savedDigits;
188     if (decNumberIsZero(&result)) {
189         return 0;
190     } else if (decNumberIsSpecial(&result)) {
191         return -2;
192     } else if (result.bits & DECNEG) {
193         return -1;
194     } else {
195         return 1;
196     }
197 }
198 
199 
200 // -------------------------------------
201 //  Reduce - remove trailing zero digits.
202 void
reduce()203 DigitList::reduce() {
204     uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext);
205 }
206 
207 
208 // -------------------------------------
209 //  trim - remove trailing fraction zero digits.
210 void
trim()211 DigitList::trim() {
212     uprv_decNumberTrim(fDecNumber);
213 }
214 
215 // -------------------------------------
216 // Resets the digit list; sets all the digits to zero.
217 
218 void
clear()219 DigitList::clear()
220 {
221     uprv_decNumberZero(fDecNumber);
222     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
223     internalSetDouble(0.0);
224 }
225 
226 
227 /**
228  * Formats a int64_t number into a base 10 string representation, and NULL terminates it.
229  * @param number The number to format
230  * @param outputStr The string to output to.  Must be at least MAX_DIGITS+2 in length (21),
231  *                  to hold the longest int64_t value.
232  * @return the number of digits written, not including the sign.
233  */
234 static int32_t
formatBase10(int64_t number,char * outputStr)235 formatBase10(int64_t number, char *outputStr) {
236     // The number is output backwards, starting with the LSD.
237     // Fill the buffer from the far end.  After the number is complete,
238     // slide the string contents to the front.
239 
240     const int32_t MAX_IDX = MAX_DIGITS+2;
241     int32_t destIdx = MAX_IDX;
242     outputStr[--destIdx] = 0;
243 
244     int64_t  n = number;
245     if (number < 0) {   // Negative numbers are slightly larger than a postive
246         outputStr[--destIdx] = (char)(-(n % 10) + kZero);
247         n /= -10;
248     }
249     do {
250         outputStr[--destIdx] = (char)(n % 10 + kZero);
251         n /= 10;
252     } while (n > 0);
253 
254     if (number < 0) {
255         outputStr[--destIdx] = '-';
256     }
257 
258     // Slide the number to the start of the output str
259     U_ASSERT(destIdx >= 0);
260     int32_t length = MAX_IDX - destIdx;
261     uprv_memmove(outputStr, outputStr+MAX_IDX-length, length);
262 
263     return length;
264 }
265 
266 
267 // -------------------------------------
268 //
269 //  setRoundingMode()
270 //    For most modes, the meaning and names are the same between the decNumber library
271 //      (which DigitList follows) and the ICU Formatting Rounding Mode values.
272 //      The flag constants are different, however.
273 //
274 //     Note that ICU's kRoundingUnnecessary is not implemented directly by DigitList.
275 //     This mode, inherited from Java, means that numbers that would not format exactly
276 //     will return an error when formatting is attempted.
277 
278 void
setRoundingMode(DecimalFormat::ERoundingMode m)279 DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) {
280     enum rounding r;
281 
282     switch (m) {
283       case  DecimalFormat::kRoundCeiling:  r = DEC_ROUND_CEILING;   break;
284       case  DecimalFormat::kRoundFloor:    r = DEC_ROUND_FLOOR;     break;
285       case  DecimalFormat::kRoundDown:     r = DEC_ROUND_DOWN;      break;
286       case  DecimalFormat::kRoundUp:       r = DEC_ROUND_UP;        break;
287       case  DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break;
288       case  DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break;
289       case  DecimalFormat::kRoundHalfUp:   r = DEC_ROUND_HALF_UP;   break;
290       case  DecimalFormat::kRoundUnnecessary: r = DEC_ROUND_HALF_EVEN; break;
291       default:
292          // TODO: how to report the problem?
293          // Leave existing mode unchanged.
294          r = uprv_decContextGetRounding(&fContext);
295     }
296     uprv_decContextSetRounding(&fContext, r);
297 
298 }
299 
300 
301 // -------------------------------------
302 
303 void
setPositive(UBool s)304 DigitList::setPositive(UBool s) {
305     if (s) {
306         fDecNumber->bits &= ~DECNEG;
307     } else {
308         fDecNumber->bits |= DECNEG;
309     }
310     internalClear();
311 }
312 // -------------------------------------
313 
314 void
setDecimalAt(int32_t d)315 DigitList::setDecimalAt(int32_t d) {
316     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
317     U_ASSERT(d-1>-999999999);
318     U_ASSERT(d-1< 999999999);
319     int32_t adjustedDigits = fDecNumber->digits;
320     if (decNumberIsZero(fDecNumber)) {
321         // Account for difference in how zero is represented between DigitList & decNumber.
322         adjustedDigits = 0;
323     }
324     fDecNumber->exponent = d - adjustedDigits;
325     internalClear();
326 }
327 
328 int32_t
getDecimalAt()329 DigitList::getDecimalAt() {
330     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
331     if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) {
332         return fDecNumber->exponent;  // Exponent should be zero for these cases.
333     }
334     return fDecNumber->exponent + fDecNumber->digits;
335 }
336 
337 void
setCount(int32_t c)338 DigitList::setCount(int32_t c)  {
339     U_ASSERT(c <= fContext.digits);
340     if (c == 0) {
341         // For a value of zero, DigitList sets all fields to zero, while
342         // decNumber keeps one digit (with that digit being a zero)
343         c = 1;
344         fDecNumber->lsu[0] = 0;
345     }
346     fDecNumber->digits = c;
347     internalClear();
348 }
349 
350 int32_t
getCount() const351 DigitList::getCount() const {
352     if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) {
353        // The extra test for exponent==0 is needed because parsing sometimes appends
354        // zero digits.  It's bogus, decimalFormatter parsing needs to be cleaned up.
355        return 0;
356     } else {
357        return fDecNumber->digits;
358     }
359 }
360 
361 void
setDigit(int32_t i,char v)362 DigitList::setDigit(int32_t i, char v) {
363     int32_t count = fDecNumber->digits;
364     U_ASSERT(i<count);
365     U_ASSERT(v>='0' && v<='9');
366     v &= 0x0f;
367     fDecNumber->lsu[count-i-1] = v;
368     internalClear();
369 }
370 
371 char
getDigit(int32_t i)372 DigitList::getDigit(int32_t i) {
373     int32_t count = fDecNumber->digits;
374     U_ASSERT(i<count);
375     return fDecNumber->lsu[count-i-1] + '0';
376 }
377 
378 // copied from DigitList::getDigit()
379 uint8_t
getDigitValue(int32_t i)380 DigitList::getDigitValue(int32_t i) {
381     int32_t count = fDecNumber->digits;
382     U_ASSERT(i<count);
383     return fDecNumber->lsu[count-i-1];
384 }
385 
386 // -------------------------------------
387 // Appends the digit to the digit list if it's not out of scope.
388 // Ignores the digit, otherwise.
389 //
390 // This function is horribly inefficient to implement with decNumber because
391 // the digits are stored least significant first, which requires moving all
392 // existing digits down one to make space for the new one to be appended.
393 //
394 void
append(char digit)395 DigitList::append(char digit)
396 {
397     U_ASSERT(digit>='0' && digit<='9');
398     // Ignore digits which exceed the precision we can represent
399     //    And don't fix for larger precision.  Fix callers instead.
400     if (decNumberIsZero(fDecNumber)) {
401         // Zero needs to be special cased because of the difference in the way
402         // that the old DigitList and decNumber represent it.
403         // digit cout was zero for digitList, is one for decNumber
404         fDecNumber->lsu[0] = digit & 0x0f;
405         fDecNumber->digits = 1;
406         fDecNumber->exponent--;     // To match the old digit list implementation.
407     } else {
408         int32_t nDigits = fDecNumber->digits;
409         if (nDigits < fContext.digits) {
410             int i;
411             for (i=nDigits; i>0; i--) {
412                 fDecNumber->lsu[i] = fDecNumber->lsu[i-1];
413             }
414             fDecNumber->lsu[0] = digit & 0x0f;
415             fDecNumber->digits++;
416             // DigitList emulation - appending doesn't change the magnitude of existing
417             //                       digits.  With decNumber's decimal being after the
418             //                       least signficant digit, we need to adjust the exponent.
419             fDecNumber->exponent--;
420         }
421     }
422     internalClear();
423 }
424 
425 // -------------------------------------
426 
427 /**
428  * Currently, getDouble() depends on strtod() to do its conversion.
429  *
430  * WARNING!!
431  * This is an extremely costly function. ~1/2 of the conversion time
432  * can be linked to this function.
433  */
434 double
getDouble() const435 DigitList::getDouble() const
436 {
437     {
438         Mutex mutex;
439         if (fHave == kDouble) {
440             return fUnion.fDouble;
441         }
442     }
443 
444     double tDouble = 0.0;
445     if (isZero()) {
446         tDouble = 0.0;
447         if (decNumberIsNegative(fDecNumber)) {
448             tDouble /= -1;
449         }
450     } else if (isInfinite()) {
451         if (std::numeric_limits<double>::has_infinity) {
452             tDouble = std::numeric_limits<double>::infinity();
453         } else {
454             tDouble = std::numeric_limits<double>::max();
455         }
456         if (!isPositive()) {
457             tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
458         }
459     } else {
460         MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
461            // Note:  14 is a  magic constant from the decNumber library documentation,
462            //        the max number of extra characters beyond the number of digits
463            //        needed to represent the number in string form.  Add a few more
464            //        for the additional digits we retain.
465 
466         // Round down to appx. double precision, if the number is longer than that.
467         // Copy the number first, so that we don't modify the original.
468         if (getCount() > MAX_DBL_DIGITS + 3) {
469             DigitList numToConvert(*this);
470             numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
471             numToConvert.round(MAX_DBL_DIGITS+3);
472             uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias());
473             // TODO:  how many extra digits should be included for an accurate conversion?
474         } else {
475             uprv_decNumberToString(this->fDecNumber, s.getAlias());
476         }
477         U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
478 
479         char *end = NULL;
480         tDouble = decimalStrToDouble(s.getAlias(), &end);
481     }
482     {
483         Mutex mutex;
484         DigitList *nonConstThis = const_cast<DigitList *>(this);
485         nonConstThis->internalSetDouble(tDouble);
486     }
487     return tDouble;
488 }
489 
490 #if U_USE_STRTOD_L && U_PLATFORM_USES_ONLY_WIN32_API
491 # define locale_t _locale_t
492 # define freelocale _free_locale
493 # define strtod_l _strtod_l
494 #endif
495 
496 #if U_USE_STRTOD_L
497 static locale_t gCLocale = (locale_t)0;
498 #endif
499 static icu::UInitOnce gCLocaleInitOnce = U_INITONCE_INITIALIZER;
500 
501 U_CDECL_BEGIN
502 // Cleanup callback func
digitList_cleanup(void)503 static UBool U_CALLCONV digitList_cleanup(void)
504 {
505 #if U_USE_STRTOD_L
506     if (gCLocale != (locale_t)0) {
507         freelocale(gCLocale);
508     }
509 #endif
510     return TRUE;
511 }
512 // C Locale initialization func
initCLocale(void)513 static void U_CALLCONV initCLocale(void) {
514     ucln_i18n_registerCleanup(UCLN_I18N_DIGITLIST, digitList_cleanup);
515 #if U_USE_STRTOD_L
516 # if U_PLATFORM_USES_ONLY_WIN32_API
517     gCLocale = _create_locale(LC_ALL, "C");
518 # else
519     gCLocale = newlocale(LC_ALL_MASK, "C", (locale_t)0);
520 # endif
521 #endif
522 }
523 U_CDECL_END
524 
525 double
decimalStrToDouble(char * decstr,char ** end)526 DigitList::decimalStrToDouble(char *decstr, char **end) {
527     umtx_initOnce(gCLocaleInitOnce, &initCLocale);
528 #if U_USE_STRTOD_L
529     return strtod_l(decstr, end, gCLocale);
530 #else
531     char *decimalPt = strchr(decstr, '.');
532     if (decimalPt) {
533         // We need to know the decimal separator character that will be used with strtod().
534         // Depends on the C runtime global locale.
535         // Most commonly is '.'
536         char rep[MAX_DIGITS];
537         sprintf(rep, "%+1.1f", 1.0);
538         *decimalPt = rep[2];
539     }
540     return uprv_strtod(decstr, end);
541 #endif
542 }
543 
544 // -------------------------------------
545 
546 /**
547  *  convert this number to an int32_t.   Round if there is a fractional part.
548  *  Return zero if the number cannot be represented.
549  */
getLong()550 int32_t DigitList::getLong() /*const*/
551 {
552     int32_t result = 0;
553     if (getUpperExponent() > 10) {
554         // Overflow, absolute value too big.
555         return result;
556     }
557     if (fDecNumber->exponent != 0) {
558         // Force to an integer, with zero exponent, rounding if necessary.
559         //   (decNumberToInt32 will only work if the exponent is exactly zero.)
560         DigitList copy(*this);
561         DigitList zero;
562         uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext);
563         result = uprv_decNumberToInt32(copy.fDecNumber, &fContext);
564     } else {
565         result = uprv_decNumberToInt32(fDecNumber, &fContext);
566     }
567     return result;
568 }
569 
570 
571 /**
572  *  convert this number to an int64_t.   Truncate if there is a fractional part.
573  *  Return zero if the number cannot be represented.
574  */
getInt64()575 int64_t DigitList::getInt64() /*const*/ {
576     // TODO: fast conversion if fHave == fDouble
577 
578     // Truncate if non-integer.
579     // Return 0 if out of range.
580     // Range of in64_t is -9223372036854775808 to 9223372036854775807  (19 digits)
581     //
582     if (getUpperExponent() > 19) {
583         // Overflow, absolute value too big.
584         return 0;
585     }
586 
587     // The number of integer digits may differ from the number of digits stored
588     //   in the decimal number.
589     //     for 12.345  numIntDigits = 2, number->digits = 5
590     //     for 12E4    numIntDigits = 6, number->digits = 2
591     // The conversion ignores the fraction digits in the first case,
592     // and fakes up extra zero digits in the second.
593     // TODO:  It would be faster to store a table of powers of ten to multiply by
594     //        instead of looping over zero digits, multiplying each time.
595 
596     int32_t numIntDigits = getUpperExponent();
597     uint64_t value = 0;
598     for (int32_t i = 0; i < numIntDigits; i++) {
599         // Loop is iterating over digits starting with the most significant.
600         // Numbers are stored with the least significant digit at index zero.
601         int32_t digitIndex = fDecNumber->digits - i - 1;
602         int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0;
603         value = value * (uint64_t)10 + (uint64_t)v;
604     }
605 
606     if (decNumberIsNegative(fDecNumber)) {
607         value = ~value;
608         value += 1;
609     }
610     int64_t svalue = (int64_t)value;
611 
612     // Check overflow.  It's convenient that the MSD is 9 only on overflow, the amount of
613     //                  overflow can't wrap too far.  The test will also fail -0, but
614     //                  that does no harm; the right answer is 0.
615     if (numIntDigits == 19) {
616         if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
617             (!decNumberIsNegative(fDecNumber) && svalue<0)) {
618             svalue = 0;
619         }
620     }
621 
622     return svalue;
623 }
624 
625 
626 /**
627  *  Return a string form of this number.
628  *     Format is as defined by the decNumber library, for interchange of
629  *     decimal numbers.
630  */
getDecimal(CharString & str,UErrorCode & status)631 void DigitList::getDecimal(CharString &str, UErrorCode &status) {
632     if (U_FAILURE(status)) {
633         return;
634     }
635 
636     // A decimal number in string form can, worst case, be 14 characters longer
637     //  than the number of digits.  So says the decNumber library doc.
638     int32_t maxLength = fDecNumber->digits + 14;
639     int32_t capacity = 0;
640     char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status);
641     if (U_FAILURE(status)) {
642         return;    // Memory allocation error on growing the string.
643     }
644     U_ASSERT(capacity >= maxLength);
645     uprv_decNumberToString(this->fDecNumber, buffer);
646     U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength);
647     str.append(buffer, -1, status);
648 }
649 
650 /**
651  * Return true if this is an integer value that can be held
652  * by an int32_t type.
653  */
654 UBool
fitsIntoLong(UBool ignoreNegativeZero)655 DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/
656 {
657     if (decNumberIsSpecial(this->fDecNumber)) {
658         // NaN or Infinity.  Does not fit in int32.
659         return FALSE;
660     }
661     uprv_decNumberTrim(this->fDecNumber);
662     if (fDecNumber->exponent < 0) {
663         // Number contains fraction digits.
664         return FALSE;
665     }
666     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
667         (fDecNumber->bits & DECNEG) != 0) {
668         // Negative Zero, not ingored.  Cannot represent as a long.
669         return FALSE;
670     }
671     if (getUpperExponent() < 10) {
672         // The number is 9 or fewer digits.
673         // The max and min int32 are 10 digts, so this number fits.
674         // This is the common case.
675         return TRUE;
676     }
677 
678     // TODO:  Should cache these constants; construction is relatively costly.
679     //        But not of huge consequence; they're only needed for 10 digit ints.
680     UErrorCode status = U_ZERO_ERROR;
681     DigitList min32; min32.set("-2147483648", status);
682     if (this->compare(min32) < 0) {
683         return FALSE;
684     }
685     DigitList max32; max32.set("2147483647", status);
686     if (this->compare(max32) > 0) {
687         return FALSE;
688     }
689     if (U_FAILURE(status)) {
690         return FALSE;
691     }
692     return true;
693 }
694 
695 
696 
697 /**
698  * Return true if the number represented by this object can fit into
699  * a long.
700  */
701 UBool
fitsIntoInt64(UBool ignoreNegativeZero)702 DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
703 {
704     if (decNumberIsSpecial(this->fDecNumber)) {
705         // NaN or Infinity.  Does not fit in int32.
706         return FALSE;
707     }
708     uprv_decNumberTrim(this->fDecNumber);
709     if (fDecNumber->exponent < 0) {
710         // Number contains fraction digits.
711         return FALSE;
712     }
713     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
714         (fDecNumber->bits & DECNEG) != 0) {
715         // Negative Zero, not ingored.  Cannot represent as a long.
716         return FALSE;
717     }
718     if (getUpperExponent() < 19) {
719         // The number is 18 or fewer digits.
720         // The max and min int64 are 19 digts, so this number fits.
721         // This is the common case.
722         return TRUE;
723     }
724 
725     // TODO:  Should cache these constants; construction is relatively costly.
726     //        But not of huge consequence; they're only needed for 19 digit ints.
727     UErrorCode status = U_ZERO_ERROR;
728     DigitList min64; min64.set("-9223372036854775808", status);
729     if (this->compare(min64) < 0) {
730         return FALSE;
731     }
732     DigitList max64; max64.set("9223372036854775807", status);
733     if (this->compare(max64) > 0) {
734         return FALSE;
735     }
736     if (U_FAILURE(status)) {
737         return FALSE;
738     }
739     return true;
740 }
741 
742 
743 // -------------------------------------
744 
745 void
set(int32_t source)746 DigitList::set(int32_t source)
747 {
748     set((int64_t)source);
749     internalSetDouble(source);
750 }
751 
752 // -------------------------------------
753 /**
754  * Set an int64, via decnumber
755  */
756 void
set(int64_t source)757 DigitList::set(int64_t source)
758 {
759     char str[MAX_DIGITS+2];   // Leave room for sign and trailing nul.
760     formatBase10(source, str);
761     U_ASSERT(uprv_strlen(str) < sizeof(str));
762 
763     uprv_decNumberFromString(fDecNumber, str, &fContext);
764     internalSetDouble(static_cast<double>(source));
765 }
766 
767 // -------------------------------------
768 /**
769  * Set the DigitList from a decimal number string.
770  *
771  * The incoming string _must_ be nul terminated, even though it is arriving
772  * as a StringPiece because that is what the decNumber library wants.
773  * We can get away with this for an internal function; it would not
774  * be acceptable for a public API.
775  */
776 void
set(StringPiece source,UErrorCode & status,uint32_t)777 DigitList::set(StringPiece source, UErrorCode &status, uint32_t /*fastpathBits*/) {
778     if (U_FAILURE(status)) {
779         return;
780     }
781 
782 #if 0
783     if(fastpathBits==(kFastpathOk|kNoDecimal)) {
784       int32_t size = source.size();
785       const char *data = source.data();
786       int64_t r = 0;
787       int64_t m = 1;
788       // fast parse
789       while(size>0) {
790         char ch = data[--size];
791         if(ch=='+') {
792           break;
793         } else if(ch=='-') {
794           r = -r;
795           break;
796         } else {
797           int64_t d = ch-'0';
798           //printf("CH[%d]=%c, %d, *=%d\n", size,ch, (int)d, (int)m);
799           r+=(d)*m;
800           m *= 10;
801         }
802       }
803       //printf("R=%d\n", r);
804       set(r);
805     } else
806 #endif
807         {
808       // Figure out a max number of digits to use during the conversion, and
809       // resize the number up if necessary.
810       int32_t numDigits = source.length();
811       if (numDigits > fContext.digits) {
812         // fContext.digits == fStorage.getCapacity()
813         decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
814         if (t == NULL) {
815           status = U_MEMORY_ALLOCATION_ERROR;
816           return;
817         }
818         fDecNumber = t;
819         fContext.digits = numDigits;
820       }
821 
822       fContext.status = 0;
823       uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
824       if ((fContext.status & DEC_Conversion_syntax) != 0) {
825         status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
826       }
827     }
828     internalClear();
829 }
830 
831 /**
832  * Set the digit list to a representation of the given double value.
833  * This method supports both fixed-point and exponential notation.
834  * @param source Value to be converted.
835  */
836 void
set(double source)837 DigitList::set(double source)
838 {
839     // for now, simple implementation; later, do proper IEEE stuff
840     char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough)
841 
842     // Generate a representation of the form /[+-][0-9].[0-9]+e[+-][0-9]+/
843     // Can also generate /[+-]nan/ or /[+-]inf/
844     // TODO: Use something other than sprintf() here, since it's behavior is somewhat platform specific.
845     //       That is why infinity is special cased here.
846     if (uprv_isInfinite(source)) {
847         if (uprv_isNegativeInfinity(source)) {
848             uprv_strcpy(rep,"-inf"); // Handle negative infinity
849         } else {
850             uprv_strcpy(rep,"inf");
851         }
852     } else {
853         sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
854     }
855     U_ASSERT(uprv_strlen(rep) < sizeof(rep));
856 
857     // uprv_decNumberFromString() will parse the string expecting '.' as a
858     // decimal separator, however sprintf() can use ',' in certain locales.
859     // Overwrite a ',' with '.' here before proceeding.
860     char *decimalSeparator = strchr(rep, ',');
861     if (decimalSeparator != NULL) {
862         *decimalSeparator = '.';
863     }
864 
865     // Create a decNumber from the string.
866     uprv_decNumberFromString(fDecNumber, rep, &fContext);
867     uprv_decNumberTrim(fDecNumber);
868     internalSetDouble(source);
869 }
870 
871 // -------------------------------------
872 
873 /*
874  * Multiply
875  *      The number will be expanded if need be to retain full precision.
876  *      In practice, for formatting, multiply is by 10, 100 or 1000, so more digits
877  *      will not be required for this use.
878  */
879 void
mult(const DigitList & other,UErrorCode & status)880 DigitList::mult(const DigitList &other, UErrorCode &status) {
881     if (U_FAILURE(status)) {
882         return;
883     }
884     fContext.status = 0;
885     int32_t requiredDigits = this->digits() + other.digits();
886     if (requiredDigits > fContext.digits) {
887         reduce();    // Remove any trailing zeros
888         int32_t requiredDigits = this->digits() + other.digits();
889         ensureCapacity(requiredDigits, status);
890     }
891     uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
892     internalClear();
893 }
894 
895 // -------------------------------------
896 
897 /*
898  * Divide
899  *      The number will _not_ be expanded for inexact results.
900  *      TODO:  probably should expand some, for rounding increments that
901  *             could add a few digits, e.g. .25, but not expand arbitrarily.
902  */
903 void
div(const DigitList & other,UErrorCode & status)904 DigitList::div(const DigitList &other, UErrorCode &status) {
905     if (U_FAILURE(status)) {
906         return;
907     }
908     uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
909     internalClear();
910 }
911 
912 // -------------------------------------
913 
914 /*
915  * ensureCapacity.   Grow the digit storage for the number if it's less than the requested
916  *         amount.  Never reduce it.  Available size is kept in fContext.digits.
917  */
918 void
ensureCapacity(int32_t requestedCapacity,UErrorCode & status)919 DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) {
920     if (U_FAILURE(status)) {
921         return;
922     }
923     if (requestedCapacity <= 0) {
924         status = U_ILLEGAL_ARGUMENT_ERROR;
925         return;
926     }
927     if (requestedCapacity > DEC_MAX_DIGITS) {
928         // Don't report an error for requesting too much.
929         // Arithemetic Results will be rounded to what can be supported.
930         //   At 999,999,999 max digits, exceeding the limit is not too likely!
931         requestedCapacity = DEC_MAX_DIGITS;
932     }
933     if (requestedCapacity > fContext.digits) {
934         decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity());
935         if (newBuffer == NULL) {
936             status = U_MEMORY_ALLOCATION_ERROR;
937             return;
938         }
939         fContext.digits = requestedCapacity;
940         fDecNumber = newBuffer;
941     }
942 }
943 
944 // -------------------------------------
945 
946 /**
947  * Round the representation to the given number of digits.
948  * @param maximumDigits The maximum number of digits to be shown.
949  * Upon return, count will be less than or equal to maximumDigits.
950  */
951 void
round(int32_t maximumDigits)952 DigitList::round(int32_t maximumDigits)
953 {
954     reduce();
955     if (maximumDigits >= fDecNumber->digits) {
956         return;
957     }
958     int32_t savedDigits  = fContext.digits;
959     fContext.digits = maximumDigits;
960     uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
961     fContext.digits = savedDigits;
962     uprv_decNumberTrim(fDecNumber);
963     reduce();
964     internalClear();
965 }
966 
967 
968 void
roundFixedPoint(int32_t maximumFractionDigits)969 DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
970     reduce();        // Remove trailing zeros.
971     if (fDecNumber->exponent >= -maximumFractionDigits) {
972         return;
973     }
974     decNumber scale;   // Dummy decimal number, but with the desired number of
975     uprv_decNumberZero(&scale);    //    fraction digits.
976     scale.exponent = -maximumFractionDigits;
977     scale.lsu[0] = 1;
978 
979     uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
980     reduce();
981     internalClear();
982 }
983 
984 // -------------------------------------
985 
986 void
toIntegralValue()987 DigitList::toIntegralValue() {
988     uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext);
989 }
990 
991 
992 // -------------------------------------
993 UBool
isZero() const994 DigitList::isZero() const
995 {
996     return decNumberIsZero(fDecNumber);
997 }
998 
999 // -------------------------------------
1000 int32_t
getUpperExponent() const1001 DigitList::getUpperExponent() const {
1002     return fDecNumber->digits + fDecNumber->exponent;
1003 }
1004 
1005 DigitInterval &
getSmallestInterval(DigitInterval & result) const1006 DigitList::getSmallestInterval(DigitInterval &result) const {
1007     result.setLeastSignificantInclusive(fDecNumber->exponent);
1008     result.setMostSignificantExclusive(getUpperExponent());
1009     return result;
1010 }
1011 
1012 uint8_t
getDigitByExponent(int32_t exponent) const1013 DigitList::getDigitByExponent(int32_t exponent) const {
1014     int32_t idx = exponent - fDecNumber->exponent;
1015     if (idx < 0 || idx >= fDecNumber->digits) {
1016         return 0;
1017     }
1018     return fDecNumber->lsu[idx];
1019 }
1020 
1021 void
appendDigitsTo(CharString & str,UErrorCode & status) const1022 DigitList::appendDigitsTo(CharString &str, UErrorCode &status) const {
1023     str.append((const char *) fDecNumber->lsu, fDecNumber->digits, status);
1024 }
1025 
1026 void
roundAtExponent(int32_t exponent,int32_t maxSigDigits)1027 DigitList::roundAtExponent(int32_t exponent, int32_t maxSigDigits) {
1028     reduce();
1029     if (maxSigDigits < fDecNumber->digits) {
1030         int32_t minExponent = getUpperExponent() - maxSigDigits;
1031         if (exponent < minExponent) {
1032             exponent = minExponent;
1033         }
1034     }
1035     if (exponent <= fDecNumber->exponent) {
1036         return;
1037     }
1038     int32_t digits = getUpperExponent() - exponent;
1039     if (digits > 0) {
1040         round(digits);
1041     } else {
1042         roundFixedPoint(-exponent);
1043     }
1044 }
1045 
1046 void
quantize(const DigitList & quantity,UErrorCode & status)1047 DigitList::quantize(const DigitList &quantity, UErrorCode &status) {
1048     if (U_FAILURE(status)) {
1049         return;
1050     }
1051     div(quantity, status);
1052     roundAtExponent(0);
1053     mult(quantity, status);
1054     reduce();
1055 }
1056 
1057 int32_t
getScientificExponent(int32_t minIntDigitCount,int32_t exponentMultiplier) const1058 DigitList::getScientificExponent(
1059         int32_t minIntDigitCount, int32_t exponentMultiplier) const {
1060     // The exponent for zero is always zero.
1061     if (isZero()) {
1062         return 0;
1063     }
1064     int32_t intDigitCount = getUpperExponent();
1065     int32_t exponent;
1066     if (intDigitCount >= minIntDigitCount) {
1067         int32_t maxAdjustment = intDigitCount - minIntDigitCount;
1068         exponent = (maxAdjustment / exponentMultiplier) * exponentMultiplier;
1069     } else {
1070         int32_t minAdjustment = minIntDigitCount - intDigitCount;
1071         exponent = ((minAdjustment + exponentMultiplier - 1) / exponentMultiplier) * -exponentMultiplier;
1072     }
1073     return exponent;
1074 }
1075 
1076 int32_t
toScientific(int32_t minIntDigitCount,int32_t exponentMultiplier)1077 DigitList::toScientific(
1078         int32_t minIntDigitCount, int32_t exponentMultiplier) {
1079     int32_t exponent = getScientificExponent(
1080             minIntDigitCount, exponentMultiplier);
1081     shiftDecimalRight(-exponent);
1082     return exponent;
1083 }
1084 
1085 void
shiftDecimalRight(int32_t n)1086 DigitList::shiftDecimalRight(int32_t n) {
1087     fDecNumber->exponent += n;
1088     internalClear();
1089 }
1090 
1091 U_NAMESPACE_END
1092 #endif // #if !UCONFIG_NO_FORMATTING
1093 
1094 //eof
1095