dom/xslt/base/txDouble.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

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.

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

mercurial