1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/FloatingPoint.h"
10 #include "txXMLUtils.h"
20 * Utility class for doubles
24 * Converts the given String to a double, if the String value does not
25 * represent a double, NaN will be returned
27 class txStringToDouble
{
29 txStringToDouble() : mState(eWhitestart
), mSign(ePositive
) {}
31 void Parse(const nsAString
& aSource
) {
32 if (mState
== eIllegal
) {
37 auto len
= aSource
.Length();
38 for (; i
< len
; ++i
) {
45 } else if (c
>= '0' && c
<= '9') {
47 mBuffer
.Append((char)c
);
48 } else if (c
== '.') {
50 mBuffer
.Append((char)c
);
51 } else if (!XMLUtils::isWhitespace(c
)) {
57 if (c
>= '0' && c
<= '9') {
58 mBuffer
.Append((char)c
);
59 } else if (c
== '.') {
61 mBuffer
.Append((char)c
);
62 } else if (XMLUtils::isWhitespace(c
)) {
70 if (c
>= '0' && c
<= '9') {
71 mBuffer
.Append((char)c
);
72 } else if (XMLUtils::isWhitespace(c
)) {
80 if (!XMLUtils::isWhitespace(c
)) {
92 if (mState
== eIllegal
|| mBuffer
.IsEmpty() ||
93 (mBuffer
.Length() == 1 && mBuffer
[0] == '.')) {
94 return mozilla::UnspecifiedNaN
<double>();
96 return static_cast<double>(mSign
) * PR_strtod(mBuffer
.get(), nullptr);
100 nsAutoCString mBuffer
;
101 enum { eWhitestart
, eDecimal
, eMantissa
, eWhiteend
, eIllegal
} mState
;
102 enum { eNegative
= -1, ePositive
= 1 } mSign
;
105 double txDouble::toDouble(const nsAString
& aSrc
) {
106 txStringToDouble sink
;
108 return sink
.getDouble();
112 * Converts the value of the given double to a String, and places
113 * The result into the destination String.
114 * @return the given dest string
116 void txDouble::toString(double aValue
, nsAString
& aDest
) {
117 // check for special cases
119 if (std::isnan(aValue
)) {
120 aDest
.AppendLiteral("NaN");
123 if (std::isinf(aValue
)) {
124 if (aValue
< 0) aDest
.Append(char16_t('-'));
125 aDest
.AppendLiteral("Infinity");
129 // Mantissa length is 17, so this is plenty
130 const int buflen
= 20;
135 PR_dtoa(aValue
, 0, 0, &intDigits
, &sign
, &endp
, buf
, buflen
- 1);
138 int32_t length
= endp
- buf
;
139 if (length
> intDigits
) {
140 // decimal point needed
143 // leading zeros, -intDigits + 1
144 length
+= 1 - intDigits
;
147 // trailing zeros, total length given by intDigits
150 if (aValue
< 0) ++length
;
152 uint32_t oldlength
= aDest
.Length();
153 if (!aDest
.SetLength(oldlength
+ length
, mozilla::fallible
))
154 return; // out of memory
155 auto dest
= aDest
.BeginWriting();
156 std::advance(dest
, oldlength
);
168 for (i
= 0; i
> intDigits
; --i
) {
174 int firstlen
= std::min
<size_t>(intDigits
, endp
- buf
);
175 for (i
= 0; i
< firstlen
; i
++) {
179 if (i
< endp
- buf
) {
184 for (; i
< endp
- buf
; i
++) {
190 for (; i
< intDigits
; i
++) {