Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
8 #include "nsString.h"
9 #include "txCore.h"
10 #include "txXMLUtils.h"
11 #include <math.h>
12 #include <stdlib.h>
13 #include <algorithm>
14 #ifdef WIN32
15 #include <float.h>
16 #endif
17 #include "prdtoa.h"
19 /*
20 * Utility class for doubles
21 */
23 /*
24 * Converts the given String to a double, if the String value does not
25 * represent a double, NaN will be returned
26 */
27 class txStringToDouble
28 {
29 public:
30 typedef char16_t input_type;
31 typedef char16_t value_type;
32 txStringToDouble(): mState(eWhitestart), mSign(ePositive) {}
34 void
35 write(const input_type* aSource, uint32_t aSourceLength)
36 {
37 if (mState == eIllegal) {
38 return;
39 }
40 uint32_t i = 0;
41 char16_t c;
42 for ( ; i < aSourceLength; ++i) {
43 c = aSource[i];
44 switch (mState) {
45 case eWhitestart:
46 if (c == '-') {
47 mState = eDecimal;
48 mSign = eNegative;
49 }
50 else if (c >= '0' && c <= '9') {
51 mState = eDecimal;
52 mBuffer.Append((char)c);
53 }
54 else if (c == '.') {
55 mState = eMantissa;
56 mBuffer.Append((char)c);
57 }
58 else if (!XMLUtils::isWhitespace(c)) {
59 mState = eIllegal;
60 return;
61 }
62 break;
63 case eDecimal:
64 if (c >= '0' && c <= '9') {
65 mBuffer.Append((char)c);
66 }
67 else if (c == '.') {
68 mState = eMantissa;
69 mBuffer.Append((char)c);
70 }
71 else if (XMLUtils::isWhitespace(c)) {
72 mState = eWhiteend;
73 }
74 else {
75 mState = eIllegal;
76 return;
77 }
78 break;
79 case eMantissa:
80 if (c >= '0' && c <= '9') {
81 mBuffer.Append((char)c);
82 }
83 else if (XMLUtils::isWhitespace(c)) {
84 mState = eWhiteend;
85 }
86 else {
87 mState = eIllegal;
88 return;
89 }
90 break;
91 case eWhiteend:
92 if (!XMLUtils::isWhitespace(c)) {
93 mState = eIllegal;
94 return;
95 }
96 break;
97 default:
98 break;
99 }
100 }
101 }
103 double
104 getDouble()
105 {
106 if (mState == eIllegal || mBuffer.IsEmpty() ||
107 (mBuffer.Length() == 1 && mBuffer[0] == '.')) {
108 return mozilla::UnspecifiedNaN<double>();
109 }
110 return mSign*PR_strtod(mBuffer.get(), 0);
111 }
112 private:
113 nsAutoCString mBuffer;
114 enum {
115 eWhitestart,
116 eDecimal,
117 eMantissa,
118 eWhiteend,
119 eIllegal
120 } mState;
121 enum {
122 eNegative = -1,
123 ePositive = 1
124 } mSign;
125 };
127 double txDouble::toDouble(const nsAString& aSrc)
128 {
129 txStringToDouble sink;
130 nsAString::const_iterator fromBegin, fromEnd;
131 copy_string(aSrc.BeginReading(fromBegin), aSrc.EndReading(fromEnd), sink);
132 return sink.getDouble();
133 }
135 /*
136 * Converts the value of the given double to a String, and places
137 * The result into the destination String.
138 * @return the given dest string
139 */
140 void txDouble::toString(double aValue, nsAString& aDest)
141 {
143 // check for special cases
145 if (mozilla::IsNaN(aValue)) {
146 aDest.AppendLiteral("NaN");
147 return;
148 }
149 if (mozilla::IsInfinite(aValue)) {
150 if (aValue < 0)
151 aDest.Append(char16_t('-'));
152 aDest.AppendLiteral("Infinity");
153 return;
154 }
156 // Mantissa length is 17, so this is plenty
157 const int buflen = 20;
158 char buf[buflen];
160 int intDigits, sign;
161 char* endp;
162 PR_dtoa(aValue, 0, 0, &intDigits, &sign, &endp, buf, buflen - 1);
164 // compute length
165 int32_t length = endp - buf;
166 if (length > intDigits) {
167 // decimal point needed
168 ++length;
169 if (intDigits < 1) {
170 // leading zeros, -intDigits + 1
171 length += 1 - intDigits;
172 }
173 }
174 else {
175 // trailing zeros, total length given by intDigits
176 length = intDigits;
177 }
178 if (aValue < 0)
179 ++length;
180 // grow the string
181 uint32_t oldlength = aDest.Length();
182 if (!aDest.SetLength(oldlength + length, mozilla::fallible_t()))
183 return; // out of memory
184 nsAString::iterator dest;
185 aDest.BeginWriting(dest).advance(int32_t(oldlength));
186 if (aValue < 0) {
187 *dest = '-'; ++dest;
188 }
189 int i;
190 // leading zeros
191 if (intDigits < 1) {
192 *dest = '0'; ++dest;
193 *dest = '.'; ++dest;
194 for (i = 0; i > intDigits; --i) {
195 *dest = '0'; ++dest;
196 }
197 }
198 // mantissa
199 int firstlen = std::min<size_t>(intDigits, endp - buf);
200 for (i = 0; i < firstlen; i++) {
201 *dest = buf[i]; ++dest;
202 }
203 if (i < endp - buf) {
204 if (i > 0) {
205 *dest = '.'; ++dest;
206 }
207 for (; i < endp - buf; i++) {
208 *dest = buf[i]; ++dest;
209 }
210 }
211 // trailing zeros
212 for (; i < intDigits; i++) {
213 *dest = '0'; ++dest;
214 }
215 }