]>
git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/visibledigits.cpp
2 * Copyright (C) 2015, International Business Machines
3 * Corporation and others. All Rights Reserved.
5 * file name: visibledigits.cpp
10 #include "unicode/utypes.h"
12 #if !UCONFIG_NO_FORMATTING
15 #include "decNumber.h"
18 #include "visibledigits.h"
20 static const int32_t kNegative
= 1;
21 static const int32_t kInfinite
= 2;
22 static const int32_t kNaN
= 4;
26 void VisibleDigits::setNegative() {
30 void VisibleDigits::setNaN() {
34 void VisibleDigits::setInfinite() {
38 void VisibleDigits::clear() {
44 fAbsIntValueSet
= FALSE
;
45 fAbsDoubleValue
= 0.0;
46 fAbsDoubleValueSet
= FALSE
;
49 UBool
VisibleDigits::isNegative() const {
50 return (fFlags
& kNegative
);
53 UBool
VisibleDigits::isNaN() const {
54 return (fFlags
& kNaN
);
57 UBool
VisibleDigits::isInfinite() const {
58 return (fFlags
& kInfinite
);
61 int32_t VisibleDigits::getDigitByExponent(int32_t digitPos
) const {
62 if (digitPos
< fExponent
|| digitPos
>= fExponent
+ fDigits
.length()) {
65 const char *ptr
= fDigits
.data();
66 return ptr
[digitPos
- fExponent
];
69 UBool
VisibleDigits::isOverMaxDigits() const {
70 return (fExponent
+ fDigits
.length() > fInterval
.getMostSignificantExclusive());
73 UBool
VisibleDigits::isNaNOrInfinity() const {
74 return (fFlags
& (kInfinite
| kNaN
)) != 0;
77 double VisibleDigits::computeAbsDoubleValue() const {
78 // Take care of NaN and infinity
83 return uprv_getInfinity();
86 // stack allocate a decNumber to hold MAX_DBL_DIGITS+3 significant digits
87 char rawNumber
[sizeof(decNumber
) + MAX_DBL_DIGITS
+3];
88 decNumber
*numberPtr
= (decNumber
*) rawNumber
;
90 int32_t mostSig
= fInterval
.getMostSignificantExclusive();
91 int32_t mostSigNonZero
= fExponent
+ fDigits
.length();
92 int32_t end
= mostSig
> mostSigNonZero
? mostSigNonZero
: mostSig
;
93 int32_t leastSig
= fInterval
.getLeastSignificantInclusive();
94 int32_t start
= leastSig
> fExponent
? leastSig
: fExponent
;
98 if (start
< end
- (MAX_DBL_DIGITS
+3)) {
99 start
= end
- (MAX_DBL_DIGITS
+3);
101 uint8_t *pos
= numberPtr
->lsu
;
102 const char *src
= &(fDigits
.data()[start
- fExponent
]);
103 for (int32_t i
= start
; i
< end
; ++i
) {
104 *pos
++ = (uint8_t) (*src
++);
106 numberPtr
->exponent
= start
;
108 numberPtr
->digits
= end
- start
;
109 char str
[MAX_DBL_DIGITS
+18];
110 uprv_decNumberToString(numberPtr
, str
);
111 U_ASSERT(uprv_strlen(str
) < MAX_DBL_DIGITS
+18);
112 char decimalSeparator
= DigitList::getStrtodDecimalSeparator();
113 if (decimalSeparator
!= '.') {
114 char *decimalPt
= strchr(str
, '.');
115 if (decimalPt
!= NULL
) {
116 *decimalPt
= decimalSeparator
;
120 return uprv_strtod(str
, &unused
);
123 void VisibleDigits::getFixedDecimal(
124 double &source
, int64_t &intValue
, int64_t &f
, int64_t &t
, int32_t &v
, UBool
&hasIntValue
) const {
131 if (isNaNOrInfinity()) {
136 if (fAbsDoubleValueSet
) {
137 source
= fAbsDoubleValue
;
139 source
= computeAbsDoubleValue();
142 // visible decimal digits
143 v
= fInterval
.getFracDigitCount();
147 // If we initialized from an int64 just use that instead of
149 if (fAbsIntValueSet
) {
150 intValue
= fAbsIntValue
;
152 int32_t startPos
= fInterval
.getMostSignificantExclusive();
156 // process the integer digits
157 for (int32_t i
= startPos
- 1; i
>= 0; --i
) {
158 intValue
= intValue
* 10LL + getDigitByExponent(i
);
160 if (intValue
== 0LL && startPos
> 0) {
161 intValue
= 100000000000000000LL;
165 // f (decimal digits)
166 // skip over any leading 0's in fraction digits.
168 for (; idx
>= -v
&& getDigitByExponent(idx
) == 0; --idx
);
170 // Only process up to first 18 non zero fraction digits for decimalDigits
171 // since that is all we can fit into an int64.
172 for (int32_t i
= idx
; i
>= -v
&& i
> idx
- 18; --i
) {
173 f
= f
* 10LL + getDigitByExponent(i
);
176 // If we have no decimal digits, we don't have an integer value
177 hasIntValue
= (f
== 0LL);
179 // t (decimal digits without trailing zeros)
181 while (t
> 0 && t
% 10LL == 0) {
187 #endif /* #if !UCONFIG_NO_FORMATTING */