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.

     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 }

mercurial