LCOV - code coverage report
Current view: top level - mfbt/double-conversion/source - double-conversion.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 56 456 12.3 %
Date: 2017-07-14 16:53:18 Functions: 4 29 13.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright 2010 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include <limits.h>
      29             : #include <math.h>
      30             : 
      31             : #include "double-conversion.h"
      32             : 
      33             : #include "bignum-dtoa.h"
      34             : #include "fast-dtoa.h"
      35             : #include "fixed-dtoa.h"
      36             : #include "ieee.h"
      37             : #include "strtod.h"
      38             : #include "utils.h"
      39             : 
      40             : namespace double_conversion {
      41             : 
      42           8 : const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
      43           8 :   int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
      44             :   static DoubleToStringConverter converter(flags,
      45             :                                            "Infinity",
      46             :                                            "NaN",
      47             :                                            'e',
      48             :                                            -6, 21,
      49           8 :                                            6, 0);
      50           8 :   return converter;
      51             : }
      52             : 
      53             : 
      54           0 : bool DoubleToStringConverter::HandleSpecialValues(
      55             :     double value,
      56             :     StringBuilder* result_builder) const {
      57           0 :   Double double_inspect(value);
      58           0 :   if (double_inspect.IsInfinite()) {
      59           0 :     if (infinity_symbol_ == NULL) return false;
      60           0 :     if (value < 0) {
      61           0 :       result_builder->AddCharacter('-');
      62             :     }
      63           0 :     result_builder->AddString(infinity_symbol_);
      64           0 :     return true;
      65             :   }
      66           0 :   if (double_inspect.IsNan()) {
      67           0 :     if (nan_symbol_ == NULL) return false;
      68           0 :     result_builder->AddString(nan_symbol_);
      69           0 :     return true;
      70             :   }
      71           0 :   return false;
      72             : }
      73             : 
      74             : 
      75           0 : void DoubleToStringConverter::CreateExponentialRepresentation(
      76             :     const char* decimal_digits,
      77             :     int length,
      78             :     int exponent,
      79             :     StringBuilder* result_builder) const {
      80           0 :   ASSERT(length != 0);
      81           0 :   result_builder->AddCharacter(decimal_digits[0]);
      82           0 :   if (length != 1) {
      83           0 :     result_builder->AddCharacter('.');
      84           0 :     result_builder->AddSubstring(&decimal_digits[1], length-1);
      85             :   }
      86           0 :   result_builder->AddCharacter(exponent_character_);
      87           0 :   if (exponent < 0) {
      88           0 :     result_builder->AddCharacter('-');
      89           0 :     exponent = -exponent;
      90             :   } else {
      91           0 :     if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
      92           0 :       result_builder->AddCharacter('+');
      93             :     }
      94             :   }
      95           0 :   if (exponent == 0) {
      96           0 :     result_builder->AddCharacter('0');
      97           0 :     return;
      98             :   }
      99           0 :   ASSERT(exponent < 1e4);
     100           0 :   const int kMaxExponentLength = 5;
     101             :   char buffer[kMaxExponentLength + 1];
     102           0 :   buffer[kMaxExponentLength] = '\0';
     103           0 :   int first_char_pos = kMaxExponentLength;
     104           0 :   while (exponent > 0) {
     105           0 :     buffer[--first_char_pos] = '0' + (exponent % 10);
     106           0 :     exponent /= 10;
     107             :   }
     108           0 :   result_builder->AddSubstring(&buffer[first_char_pos],
     109           0 :                                kMaxExponentLength - first_char_pos);
     110             : }
     111             : 
     112             : 
     113           8 : void DoubleToStringConverter::CreateDecimalRepresentation(
     114             :     const char* decimal_digits,
     115             :     int length,
     116             :     int decimal_point,
     117             :     int digits_after_point,
     118             :     StringBuilder* result_builder) const {
     119             :   // Create a representation that is padded with zeros if needed.
     120           8 :   if (decimal_point <= 0) {
     121             :       // "0.00000decimal_rep" or "0.000decimal_rep00".
     122           3 :     result_builder->AddCharacter('0');
     123           3 :     if (digits_after_point > 0) {
     124           3 :       result_builder->AddCharacter('.');
     125           3 :       result_builder->AddPadding('0', -decimal_point);
     126           3 :       ASSERT(length <= digits_after_point - (-decimal_point));
     127           3 :       result_builder->AddSubstring(decimal_digits, length);
     128           3 :       int remaining_digits = digits_after_point - (-decimal_point) - length;
     129           3 :       result_builder->AddPadding('0', remaining_digits);
     130             :     }
     131           5 :   } else if (decimal_point >= length) {
     132             :     // "decimal_rep0000.00000" or "decimal_rep.0000".
     133           1 :     result_builder->AddSubstring(decimal_digits, length);
     134           1 :     result_builder->AddPadding('0', decimal_point - length);
     135           1 :     if (digits_after_point > 0) {
     136           0 :       result_builder->AddCharacter('.');
     137           0 :       result_builder->AddPadding('0', digits_after_point);
     138             :     }
     139             :   } else {
     140             :     // "decima.l_rep000".
     141           4 :     ASSERT(digits_after_point > 0);
     142           4 :     result_builder->AddSubstring(decimal_digits, decimal_point);
     143           4 :     result_builder->AddCharacter('.');
     144           4 :     ASSERT(length - decimal_point <= digits_after_point);
     145           4 :     result_builder->AddSubstring(&decimal_digits[decimal_point],
     146           4 :                                  length - decimal_point);
     147           4 :     int remaining_digits = digits_after_point - (length - decimal_point);
     148           4 :     result_builder->AddPadding('0', remaining_digits);
     149             :   }
     150           8 :   if (digits_after_point == 0) {
     151           1 :     if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
     152           0 :       result_builder->AddCharacter('.');
     153             :     }
     154           1 :     if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
     155           0 :       result_builder->AddCharacter('0');
     156             :     }
     157             :   }
     158           8 : }
     159             : 
     160             : 
     161           8 : bool DoubleToStringConverter::ToShortestIeeeNumber(
     162             :     double value,
     163             :     StringBuilder* result_builder,
     164             :     DoubleToStringConverter::DtoaMode mode) const {
     165           8 :   ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
     166           8 :   if (Double(value).IsSpecial()) {
     167           0 :     return HandleSpecialValues(value, result_builder);
     168             :   }
     169             : 
     170             :   int decimal_point;
     171             :   bool sign;
     172           8 :   const int kDecimalRepCapacity = kBase10MaximalLength + 1;
     173             :   char decimal_rep[kDecimalRepCapacity];
     174             :   int decimal_rep_length;
     175             : 
     176             :   DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
     177           8 :                 &sign, &decimal_rep_length, &decimal_point);
     178             : 
     179           8 :   bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
     180           8 :   if (sign && (value != 0.0 || !unique_zero)) {
     181           0 :     result_builder->AddCharacter('-');
     182             :   }
     183             : 
     184           8 :   int exponent = decimal_point - 1;
     185          16 :   if ((decimal_in_shortest_low_ <= exponent) &&
     186           8 :       (exponent < decimal_in_shortest_high_)) {
     187           8 :     CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
     188             :                                 decimal_point,
     189             :                                 Max(0, decimal_rep_length - decimal_point),
     190           8 :                                 result_builder);
     191             :   } else {
     192             :     CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
     193           0 :                                     result_builder);
     194             :   }
     195           8 :   return true;
     196             : }
     197             : 
     198             : 
     199           0 : bool DoubleToStringConverter::ToFixed(double value,
     200             :                                       int requested_digits,
     201             :                                       StringBuilder* result_builder) const {
     202             :   ASSERT(kMaxFixedDigitsBeforePoint == 60);
     203           0 :   const double kFirstNonFixed = 1e60;
     204             : 
     205           0 :   if (Double(value).IsSpecial()) {
     206           0 :     return HandleSpecialValues(value, result_builder);
     207             :   }
     208             : 
     209           0 :   if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
     210           0 :   if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
     211             : 
     212             :   // Find a sufficiently precise decimal representation of n.
     213             :   int decimal_point;
     214             :   bool sign;
     215             :   // Add space for the '\0' byte.
     216             :   const int kDecimalRepCapacity =
     217           0 :       kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
     218             :   char decimal_rep[kDecimalRepCapacity];
     219             :   int decimal_rep_length;
     220             :   DoubleToAscii(value, FIXED, requested_digits,
     221             :                 decimal_rep, kDecimalRepCapacity,
     222           0 :                 &sign, &decimal_rep_length, &decimal_point);
     223             : 
     224           0 :   bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
     225           0 :   if (sign && (value != 0.0 || !unique_zero)) {
     226           0 :     result_builder->AddCharacter('-');
     227             :   }
     228             : 
     229             :   CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
     230           0 :                               requested_digits, result_builder);
     231           0 :   return true;
     232             : }
     233             : 
     234             : 
     235           0 : bool DoubleToStringConverter::ToExponential(
     236             :     double value,
     237             :     int requested_digits,
     238             :     StringBuilder* result_builder) const {
     239           0 :   if (Double(value).IsSpecial()) {
     240           0 :     return HandleSpecialValues(value, result_builder);
     241             :   }
     242             : 
     243           0 :   if (requested_digits < -1) return false;
     244           0 :   if (requested_digits > kMaxExponentialDigits) return false;
     245             : 
     246             :   int decimal_point;
     247             :   bool sign;
     248             :   // Add space for digit before the decimal point and the '\0' character.
     249           0 :   const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
     250             :   ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
     251             :   char decimal_rep[kDecimalRepCapacity];
     252             :   int decimal_rep_length;
     253             : 
     254           0 :   if (requested_digits == -1) {
     255             :     DoubleToAscii(value, SHORTEST, 0,
     256             :                   decimal_rep, kDecimalRepCapacity,
     257           0 :                   &sign, &decimal_rep_length, &decimal_point);
     258             :   } else {
     259           0 :     DoubleToAscii(value, PRECISION, requested_digits + 1,
     260             :                   decimal_rep, kDecimalRepCapacity,
     261           0 :                   &sign, &decimal_rep_length, &decimal_point);
     262           0 :     ASSERT(decimal_rep_length <= requested_digits + 1);
     263             : 
     264           0 :     for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
     265           0 :       decimal_rep[i] = '0';
     266             :     }
     267           0 :     decimal_rep_length = requested_digits + 1;
     268             :   }
     269             : 
     270           0 :   bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
     271           0 :   if (sign && (value != 0.0 || !unique_zero)) {
     272           0 :     result_builder->AddCharacter('-');
     273             :   }
     274             : 
     275           0 :   int exponent = decimal_point - 1;
     276             :   CreateExponentialRepresentation(decimal_rep,
     277             :                                   decimal_rep_length,
     278             :                                   exponent,
     279           0 :                                   result_builder);
     280           0 :   return true;
     281             : }
     282             : 
     283             : 
     284           0 : bool DoubleToStringConverter::ToPrecision(double value,
     285             :                                           int precision,
     286             :                                           bool* used_exponential_notation,
     287             :                                           StringBuilder* result_builder) const {
     288           0 :   *used_exponential_notation = false;
     289           0 :   if (Double(value).IsSpecial()) {
     290           0 :     return HandleSpecialValues(value, result_builder);
     291             :   }
     292             : 
     293           0 :   if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
     294           0 :     return false;
     295             :   }
     296             : 
     297             :   // Find a sufficiently precise decimal representation of n.
     298             :   int decimal_point;
     299             :   bool sign;
     300             :   // Add one for the terminating null character.
     301           0 :   const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
     302             :   char decimal_rep[kDecimalRepCapacity];
     303             :   int decimal_rep_length;
     304             : 
     305             :   DoubleToAscii(value, PRECISION, precision,
     306             :                 decimal_rep, kDecimalRepCapacity,
     307           0 :                 &sign, &decimal_rep_length, &decimal_point);
     308           0 :   ASSERT(decimal_rep_length <= precision);
     309             : 
     310           0 :   bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
     311           0 :   if (sign && (value != 0.0 || !unique_zero)) {
     312           0 :     result_builder->AddCharacter('-');
     313             :   }
     314             : 
     315             :   // The exponent if we print the number as x.xxeyyy. That is with the
     316             :   // decimal point after the first digit.
     317           0 :   int exponent = decimal_point - 1;
     318             : 
     319           0 :   int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
     320           0 :   if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
     321           0 :       (decimal_point - precision + extra_zero >
     322           0 :        max_trailing_padding_zeroes_in_precision_mode_)) {
     323             :     // Fill buffer to contain 'precision' digits.
     324             :     // Usually the buffer is already at the correct length, but 'DoubleToAscii'
     325             :     // is allowed to return less characters.
     326           0 :     for (int i = decimal_rep_length; i < precision; ++i) {
     327           0 :       decimal_rep[i] = '0';
     328             :     }
     329             : 
     330           0 :     *used_exponential_notation = true;
     331             :     CreateExponentialRepresentation(decimal_rep,
     332             :                                     precision,
     333             :                                     exponent,
     334           0 :                                     result_builder);
     335             :   } else {
     336           0 :     CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
     337             :                                 Max(0, precision - decimal_point),
     338           0 :                                 result_builder);
     339             :   }
     340           0 :   return true;
     341             : }
     342             : 
     343             : 
     344           0 : static BignumDtoaMode DtoaToBignumDtoaMode(
     345             :     DoubleToStringConverter::DtoaMode dtoa_mode) {
     346           0 :   switch (dtoa_mode) {
     347           0 :     case DoubleToStringConverter::SHORTEST:  return BIGNUM_DTOA_SHORTEST;
     348             :     case DoubleToStringConverter::SHORTEST_SINGLE:
     349           0 :         return BIGNUM_DTOA_SHORTEST_SINGLE;
     350           0 :     case DoubleToStringConverter::FIXED:     return BIGNUM_DTOA_FIXED;
     351           0 :     case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
     352             :     default:
     353           0 :       UNREACHABLE();
     354             :   }
     355             : }
     356             : 
     357             : 
     358           8 : void DoubleToStringConverter::DoubleToAscii(double v,
     359             :                                             DtoaMode mode,
     360             :                                             int requested_digits,
     361             :                                             char* buffer,
     362             :                                             int buffer_length,
     363             :                                             bool* sign,
     364             :                                             int* length,
     365             :                                             int* point) {
     366           8 :   Vector<char> vector(buffer, buffer_length);
     367           8 :   ASSERT(!Double(v).IsSpecial());
     368           8 :   ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
     369             : 
     370           8 :   if (Double(v).Sign() < 0) {
     371           0 :     *sign = true;
     372           0 :     v = -v;
     373             :   } else {
     374           8 :     *sign = false;
     375             :   }
     376             : 
     377           8 :   if (mode == PRECISION && requested_digits == 0) {
     378           0 :     vector[0] = '\0';
     379           0 :     *length = 0;
     380           8 :     return;
     381             :   }
     382             : 
     383           8 :   if (v == 0) {
     384           0 :     vector[0] = '0';
     385           0 :     vector[1] = '\0';
     386           0 :     *length = 1;
     387           0 :     *point = 1;
     388           0 :     return;
     389             :   }
     390             : 
     391             :   bool fast_worked;
     392           8 :   switch (mode) {
     393             :     case SHORTEST:
     394           8 :       fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
     395           8 :       break;
     396             :     case SHORTEST_SINGLE:
     397             :       fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
     398           0 :                              vector, length, point);
     399           0 :       break;
     400             :     case FIXED:
     401           0 :       fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
     402           0 :       break;
     403             :     case PRECISION:
     404             :       fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
     405           0 :                              vector, length, point);
     406           0 :       break;
     407             :     default:
     408           0 :       fast_worked = false;
     409           0 :       UNREACHABLE();
     410             :   }
     411           8 :   if (fast_worked) return;
     412             : 
     413             :   // If the fast dtoa didn't succeed use the slower bignum version.
     414           0 :   BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
     415           0 :   BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
     416           0 :   vector[*length] = '\0';
     417             : }
     418             : 
     419             : 
     420             : // Consumes the given substring from the iterator.
     421             : // Returns false, if the substring does not match.
     422             : template <class Iterator>
     423           0 : static bool ConsumeSubString(Iterator* current,
     424             :                              Iterator end,
     425             :                              const char* substring) {
     426           0 :   ASSERT(**current == *substring);
     427           0 :   for (substring++; *substring != '\0'; substring++) {
     428           0 :     ++*current;
     429           0 :     if (*current == end || **current != *substring) return false;
     430             :   }
     431           0 :   ++*current;
     432           0 :   return true;
     433             : }
     434             : 
     435             : 
     436             : // Maximum number of significant digits in decimal representation.
     437             : // The longest possible double in decimal representation is
     438             : // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
     439             : // (768 digits). If we parse a number whose first digits are equal to a
     440             : // mean of 2 adjacent doubles (that could have up to 769 digits) the result
     441             : // must be rounded to the bigger one unless the tail consists of zeros, so
     442             : // we don't need to preserve all the digits.
     443             : const int kMaxSignificantDigits = 772;
     444             : 
     445             : 
     446             : static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
     447             : static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
     448             : 
     449             : 
     450             : static const uc16 kWhitespaceTable16[] = {
     451             :   160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
     452             :   8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
     453             : };
     454             : static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
     455             : 
     456             : 
     457           0 : static bool isWhitespace(int x) {
     458           0 :   if (x < 128) {
     459           0 :     for (int i = 0; i < kWhitespaceTable7Length; i++) {
     460           0 :       if (kWhitespaceTable7[i] == x) return true;
     461             :     }
     462             :   } else {
     463           0 :     for (int i = 0; i < kWhitespaceTable16Length; i++) {
     464           0 :       if (kWhitespaceTable16[i] == x) return true;
     465             :     }
     466             :   }
     467           0 :   return false;
     468             : }
     469             : 
     470             : 
     471             : // Returns true if a nonspace found and false if the end has reached.
     472             : template <class Iterator>
     473           0 : static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
     474           0 :   while (*current != end) {
     475           0 :     if (!isWhitespace(**current)) return true;
     476           0 :     ++*current;
     477             :   }
     478           0 :   return false;
     479             : }
     480             : 
     481             : 
     482           0 : static bool isDigit(int x, int radix) {
     483           0 :   return (x >= '0' && x <= '9' && x < '0' + radix)
     484           0 :       || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
     485           0 :       || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
     486             : }
     487             : 
     488             : 
     489           0 : static double SignedZero(bool sign) {
     490           0 :   return sign ? -0.0 : 0.0;
     491             : }
     492             : 
     493             : 
     494             : // Returns true if 'c' is a decimal digit that is valid for the given radix.
     495             : //
     496             : // The function is small and could be inlined, but VS2012 emitted a warning
     497             : // because it constant-propagated the radix and concluded that the last
     498             : // condition was always true. By moving it into a separate function the
     499             : // compiler wouldn't warn anymore.
     500             : #if _MSC_VER
     501             : #pragma optimize("",off)
     502             : static bool IsDecimalDigitForRadix(int c, int radix) {
     503             :   return '0' <= c && c <= '9' && (c - '0') < radix;
     504             : }
     505             : #pragma optimize("",on)
     506             : #else
     507           0 : static bool inline IsDecimalDigitForRadix(int c, int radix) {
     508           0 :         return '0' <= c && c <= '9' && (c - '0') < radix;
     509             : }
     510             : #endif
     511             : // Returns true if 'c' is a character digit that is valid for the given radix.
     512             : // The 'a_character' should be 'a' or 'A'.
     513             : //
     514             : // The function is small and could be inlined, but VS2012 emitted a warning
     515             : // because it constant-propagated the radix and concluded that the first
     516             : // condition was always false. By moving it into a separate function the
     517             : // compiler wouldn't warn anymore.
     518           0 : static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
     519           0 :   return radix > 10 && c >= a_character && c < a_character + radix - 10;
     520             : }
     521             : 
     522             : 
     523             : // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
     524             : template <int radix_log_2, class Iterator>
     525           0 : static double RadixStringToIeee(Iterator* current,
     526             :                                 Iterator end,
     527             :                                 bool sign,
     528             :                                 bool allow_trailing_junk,
     529             :                                 double junk_string_value,
     530             :                                 bool read_as_double,
     531             :                                 bool* result_is_junk) {
     532           0 :   ASSERT(*current != end);
     533             : 
     534           0 :   const int kDoubleSize = Double::kSignificandSize;
     535           0 :   const int kSingleSize = Single::kSignificandSize;
     536           0 :   const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
     537             : 
     538           0 :   *result_is_junk = true;
     539             : 
     540             :   // Skip leading 0s.
     541           0 :   while (**current == '0') {
     542           0 :     ++(*current);
     543           0 :     if (*current == end) {
     544           0 :       *result_is_junk = false;
     545           0 :       return SignedZero(sign);
     546             :     }
     547             :   }
     548             : 
     549           0 :   int64_t number = 0;
     550           0 :   int exponent = 0;
     551           0 :   const int radix = (1 << radix_log_2);
     552             : 
     553           0 :   do {
     554             :     int digit;
     555           0 :     if (IsDecimalDigitForRadix(**current, radix)) {
     556           0 :       digit = static_cast<char>(**current) - '0';
     557           0 :     } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
     558           0 :       digit = static_cast<char>(**current) - 'a' + 10;
     559           0 :     } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
     560           0 :       digit = static_cast<char>(**current) - 'A' + 10;
     561             :     } else {
     562           0 :       if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
     563           0 :         break;
     564             :       } else {
     565           0 :         return junk_string_value;
     566             :       }
     567             :     }
     568             : 
     569           0 :     number = number * radix + digit;
     570           0 :     int overflow = static_cast<int>(number >> kSignificandSize);
     571           0 :     if (overflow != 0) {
     572             :       // Overflow occurred. Need to determine which direction to round the
     573             :       // result.
     574           0 :       int overflow_bits_count = 1;
     575           0 :       while (overflow > 1) {
     576           0 :         overflow_bits_count++;
     577           0 :         overflow >>= 1;
     578             :       }
     579             : 
     580           0 :       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
     581           0 :       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
     582           0 :       number >>= overflow_bits_count;
     583           0 :       exponent = overflow_bits_count;
     584             : 
     585           0 :       bool zero_tail = true;
     586             :       for (;;) {
     587           0 :         ++(*current);
     588           0 :         if (*current == end || !isDigit(**current, radix)) break;
     589           0 :         zero_tail = zero_tail && **current == '0';
     590           0 :         exponent += radix_log_2;
     591             :       }
     592             : 
     593           0 :       if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
     594           0 :         return junk_string_value;
     595             :       }
     596             : 
     597           0 :       int middle_value = (1 << (overflow_bits_count - 1));
     598           0 :       if (dropped_bits > middle_value) {
     599           0 :         number++;  // Rounding up.
     600           0 :       } else if (dropped_bits == middle_value) {
     601             :         // Rounding to even to consistency with decimals: half-way case rounds
     602             :         // up if significant part is odd and down otherwise.
     603           0 :         if ((number & 1) != 0 || !zero_tail) {
     604           0 :           number++;  // Rounding up.
     605             :         }
     606             :       }
     607             : 
     608             :       // Rounding up may cause overflow.
     609           0 :       if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
     610           0 :         exponent++;
     611           0 :         number >>= 1;
     612             :       }
     613           0 :       break;
     614             :     }
     615           0 :     ++(*current);
     616           0 :   } while (*current != end);
     617             : 
     618           0 :   ASSERT(number < ((int64_t)1 << kSignificandSize));
     619           0 :   ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
     620             : 
     621           0 :   *result_is_junk = false;
     622             : 
     623           0 :   if (exponent == 0) {
     624           0 :     if (sign) {
     625           0 :       if (number == 0) return -0.0;
     626           0 :       number = -number;
     627             :     }
     628           0 :     return static_cast<double>(number);
     629             :   }
     630             : 
     631           0 :   ASSERT(number != 0);
     632           0 :   return Double(DiyFp(number, exponent)).value();
     633             : }
     634             : 
     635             : 
     636             : template <class Iterator>
     637           0 : double StringToDoubleConverter::StringToIeee(
     638             :     Iterator input,
     639             :     int length,
     640             :     bool read_as_double,
     641             :     int* processed_characters_count) const {
     642           0 :   Iterator current = input;
     643           0 :   Iterator end = input + length;
     644             : 
     645           0 :   *processed_characters_count = 0;
     646             : 
     647           0 :   const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
     648           0 :   const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
     649           0 :   const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
     650           0 :   const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
     651             : 
     652             :   // To make sure that iterator dereferencing is valid the following
     653             :   // convention is used:
     654             :   // 1. Each '++current' statement is followed by check for equality to 'end'.
     655             :   // 2. If AdvanceToNonspace returned false then current == end.
     656             :   // 3. If 'current' becomes equal to 'end' the function returns or goes to
     657             :   // 'parsing_done'.
     658             :   // 4. 'current' is not dereferenced after the 'parsing_done' label.
     659             :   // 5. Code before 'parsing_done' may rely on 'current != end'.
     660           0 :   if (current == end) return empty_string_value_;
     661             : 
     662           0 :   if (allow_leading_spaces || allow_trailing_spaces) {
     663           0 :     if (!AdvanceToNonspace(&current, end)) {
     664           0 :       *processed_characters_count = static_cast<int>(current - input);
     665           0 :       return empty_string_value_;
     666             :     }
     667           0 :     if (!allow_leading_spaces && (input != current)) {
     668             :       // No leading spaces allowed, but AdvanceToNonspace moved forward.
     669           0 :       return junk_string_value_;
     670             :     }
     671             :   }
     672             : 
     673             :   // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
     674           0 :   const int kBufferSize = kMaxSignificantDigits + 10;
     675             :   char buffer[kBufferSize];  // NOLINT: size is known at compile time.
     676           0 :   int buffer_pos = 0;
     677             : 
     678             :   // Exponent will be adjusted if insignificant digits of the integer part
     679             :   // or insignificant leading zeros of the fractional part are dropped.
     680           0 :   int exponent = 0;
     681           0 :   int significant_digits = 0;
     682           0 :   int insignificant_digits = 0;
     683           0 :   bool nonzero_digit_dropped = false;
     684             : 
     685           0 :   bool sign = false;
     686             : 
     687           0 :   if (*current == '+' || *current == '-') {
     688           0 :     sign = (*current == '-');
     689           0 :     ++current;
     690           0 :     Iterator next_non_space = current;
     691             :     // Skip following spaces (if allowed).
     692           0 :     if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
     693           0 :     if (!allow_spaces_after_sign && (current != next_non_space)) {
     694           0 :       return junk_string_value_;
     695             :     }
     696           0 :     current = next_non_space;
     697             :   }
     698             : 
     699           0 :   if (infinity_symbol_ != NULL) {
     700           0 :     if (*current == infinity_symbol_[0]) {
     701           0 :       if (!ConsumeSubString(&current, end, infinity_symbol_)) {
     702           0 :         return junk_string_value_;
     703             :       }
     704             : 
     705           0 :       if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
     706           0 :         return junk_string_value_;
     707             :       }
     708           0 :       if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
     709           0 :         return junk_string_value_;
     710             :       }
     711             : 
     712           0 :       ASSERT(buffer_pos == 0);
     713           0 :       *processed_characters_count = static_cast<int>(current - input);
     714           0 :       return sign ? -Double::Infinity() : Double::Infinity();
     715             :     }
     716             :   }
     717             : 
     718           0 :   if (nan_symbol_ != NULL) {
     719           0 :     if (*current == nan_symbol_[0]) {
     720           0 :       if (!ConsumeSubString(&current, end, nan_symbol_)) {
     721           0 :         return junk_string_value_;
     722             :       }
     723             : 
     724           0 :       if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
     725           0 :         return junk_string_value_;
     726             :       }
     727           0 :       if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
     728           0 :         return junk_string_value_;
     729             :       }
     730             : 
     731           0 :       ASSERT(buffer_pos == 0);
     732           0 :       *processed_characters_count = static_cast<int>(current - input);
     733           0 :       return sign ? -Double::NaN() : Double::NaN();
     734             :     }
     735             :   }
     736             : 
     737           0 :   bool leading_zero = false;
     738           0 :   if (*current == '0') {
     739           0 :     ++current;
     740           0 :     if (current == end) {
     741           0 :       *processed_characters_count = static_cast<int>(current - input);
     742           0 :       return SignedZero(sign);
     743             :     }
     744             : 
     745           0 :     leading_zero = true;
     746             : 
     747             :     // It could be hexadecimal value.
     748           0 :     if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
     749           0 :       ++current;
     750           0 :       if (current == end || !isDigit(*current, 16)) {
     751           0 :         return junk_string_value_;  // "0x".
     752             :       }
     753             : 
     754             :       bool result_is_junk;
     755           0 :       double result = RadixStringToIeee<4>(&current,
     756             :                                            end,
     757             :                                            sign,
     758             :                                            allow_trailing_junk,
     759           0 :                                            junk_string_value_,
     760             :                                            read_as_double,
     761           0 :                                            &result_is_junk);
     762           0 :       if (!result_is_junk) {
     763           0 :         if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
     764           0 :         *processed_characters_count = static_cast<int>(current - input);
     765             :       }
     766           0 :       return result;
     767             :     }
     768             : 
     769             :     // Ignore leading zeros in the integer part.
     770           0 :     while (*current == '0') {
     771           0 :       ++current;
     772           0 :       if (current == end) {
     773           0 :         *processed_characters_count = static_cast<int>(current - input);
     774           0 :         return SignedZero(sign);
     775             :       }
     776             :     }
     777             :   }
     778             : 
     779           0 :   bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
     780             : 
     781             :   // Copy significant digits of the integer part (if any) to the buffer.
     782           0 :   while (*current >= '0' && *current <= '9') {
     783           0 :     if (significant_digits < kMaxSignificantDigits) {
     784           0 :       ASSERT(buffer_pos < kBufferSize);
     785           0 :       buffer[buffer_pos++] = static_cast<char>(*current);
     786           0 :       significant_digits++;
     787             :       // Will later check if it's an octal in the buffer.
     788             :     } else {
     789           0 :       insignificant_digits++;  // Move the digit into the exponential part.
     790           0 :       nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
     791             :     }
     792           0 :     octal = octal && *current < '8';
     793           0 :     ++current;
     794           0 :     if (current == end) goto parsing_done;
     795             :   }
     796             : 
     797           0 :   if (significant_digits == 0) {
     798           0 :     octal = false;
     799             :   }
     800             : 
     801           0 :   if (*current == '.') {
     802           0 :     if (octal && !allow_trailing_junk) return junk_string_value_;
     803           0 :     if (octal) goto parsing_done;
     804             : 
     805           0 :     ++current;
     806           0 :     if (current == end) {
     807           0 :       if (significant_digits == 0 && !leading_zero) {
     808           0 :         return junk_string_value_;
     809             :       } else {
     810             :         goto parsing_done;
     811             :       }
     812             :     }
     813             : 
     814           0 :     if (significant_digits == 0) {
     815             :       // octal = false;
     816             :       // Integer part consists of 0 or is absent. Significant digits start after
     817             :       // leading zeros (if any).
     818           0 :       while (*current == '0') {
     819           0 :         ++current;
     820           0 :         if (current == end) {
     821           0 :           *processed_characters_count = static_cast<int>(current - input);
     822           0 :           return SignedZero(sign);
     823             :         }
     824           0 :         exponent--;  // Move this 0 into the exponent.
     825             :       }
     826             :     }
     827             : 
     828             :     // There is a fractional part.
     829             :     // We don't emit a '.', but adjust the exponent instead.
     830           0 :     while (*current >= '0' && *current <= '9') {
     831           0 :       if (significant_digits < kMaxSignificantDigits) {
     832           0 :         ASSERT(buffer_pos < kBufferSize);
     833           0 :         buffer[buffer_pos++] = static_cast<char>(*current);
     834           0 :         significant_digits++;
     835           0 :         exponent--;
     836             :       } else {
     837             :         // Ignore insignificant digits in the fractional part.
     838           0 :         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
     839             :       }
     840           0 :       ++current;
     841           0 :       if (current == end) goto parsing_done;
     842             :     }
     843             :   }
     844             : 
     845           0 :   if (!leading_zero && exponent == 0 && significant_digits == 0) {
     846             :     // If leading_zeros is true then the string contains zeros.
     847             :     // If exponent < 0 then string was [+-]\.0*...
     848             :     // If significant_digits != 0 the string is not equal to 0.
     849             :     // Otherwise there are no digits in the string.
     850           0 :     return junk_string_value_;
     851             :   }
     852             : 
     853             :   // Parse exponential part.
     854           0 :   if (*current == 'e' || *current == 'E') {
     855           0 :     if (octal && !allow_trailing_junk) return junk_string_value_;
     856           0 :     if (octal) goto parsing_done;
     857           0 :     ++current;
     858           0 :     if (current == end) {
     859           0 :       if (allow_trailing_junk) {
     860           0 :         goto parsing_done;
     861             :       } else {
     862           0 :         return junk_string_value_;
     863             :       }
     864             :     }
     865           0 :     char exponen_sign = '+';
     866           0 :     if (*current == '+' || *current == '-') {
     867           0 :       exponen_sign = static_cast<char>(*current);
     868           0 :       ++current;
     869           0 :       if (current == end) {
     870           0 :         if (allow_trailing_junk) {
     871           0 :           goto parsing_done;
     872             :         } else {
     873           0 :           return junk_string_value_;
     874             :         }
     875             :       }
     876             :     }
     877             : 
     878           0 :     if (current == end || *current < '0' || *current > '9') {
     879           0 :       if (allow_trailing_junk) {
     880           0 :         goto parsing_done;
     881             :       } else {
     882           0 :         return junk_string_value_;
     883             :       }
     884             :     }
     885             : 
     886           0 :     const int max_exponent = INT_MAX / 2;
     887           0 :     ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
     888           0 :     int num = 0;
     889           0 :     do {
     890             :       // Check overflow.
     891           0 :       int digit = *current - '0';
     892           0 :       if (num >= max_exponent / 10
     893           0 :           && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
     894           0 :         num = max_exponent;
     895             :       } else {
     896           0 :         num = num * 10 + digit;
     897             :       }
     898           0 :       ++current;
     899           0 :     } while (current != end && *current >= '0' && *current <= '9');
     900             : 
     901           0 :     exponent += (exponen_sign == '-' ? -num : num);
     902             :   }
     903             : 
     904           0 :   if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
     905           0 :     return junk_string_value_;
     906             :   }
     907           0 :   if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
     908           0 :     return junk_string_value_;
     909             :   }
     910           0 :   if (allow_trailing_spaces) {
     911           0 :     AdvanceToNonspace(&current, end);
     912             :   }
     913             : 
     914             :   parsing_done:
     915           0 :   exponent += insignificant_digits;
     916             : 
     917           0 :   if (octal) {
     918             :     double result;
     919             :     bool result_is_junk;
     920           0 :     char* start = buffer;
     921           0 :     result = RadixStringToIeee<3>(&start,
     922             :                                   buffer + buffer_pos,
     923             :                                   sign,
     924             :                                   allow_trailing_junk,
     925           0 :                                   junk_string_value_,
     926             :                                   read_as_double,
     927             :                                   &result_is_junk);
     928           0 :     ASSERT(!result_is_junk);
     929           0 :     *processed_characters_count = static_cast<int>(current - input);
     930           0 :     return result;
     931             :   }
     932             : 
     933           0 :   if (nonzero_digit_dropped) {
     934           0 :     buffer[buffer_pos++] = '1';
     935           0 :     exponent--;
     936             :   }
     937             : 
     938           0 :   ASSERT(buffer_pos < kBufferSize);
     939           0 :   buffer[buffer_pos] = '\0';
     940             : 
     941             :   double converted;
     942           0 :   if (read_as_double) {
     943           0 :     converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
     944             :   } else {
     945           0 :     converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
     946             :   }
     947           0 :   *processed_characters_count = static_cast<int>(current - input);
     948           0 :   return sign? -converted: converted;
     949             : }
     950             : 
     951             : 
     952           0 : double StringToDoubleConverter::StringToDouble(
     953             :     const char* buffer,
     954             :     int length,
     955             :     int* processed_characters_count) const {
     956           0 :   return StringToIeee(buffer, length, true, processed_characters_count);
     957             : }
     958             : 
     959             : 
     960           0 : double StringToDoubleConverter::StringToDouble(
     961             :     const uc16* buffer,
     962             :     int length,
     963             :     int* processed_characters_count) const {
     964           0 :   return StringToIeee(buffer, length, true, processed_characters_count);
     965             : }
     966             : 
     967             : 
     968           0 : float StringToDoubleConverter::StringToFloat(
     969             :     const char* buffer,
     970             :     int length,
     971             :     int* processed_characters_count) const {
     972           0 :   return static_cast<float>(StringToIeee(buffer, length, false,
     973           0 :                                          processed_characters_count));
     974             : }
     975             : 
     976             : 
     977           0 : float StringToDoubleConverter::StringToFloat(
     978             :     const uc16* buffer,
     979             :     int length,
     980             :     int* processed_characters_count) const {
     981           0 :   return static_cast<float>(StringToIeee(buffer, length, false,
     982           0 :                                          processed_characters_count));
     983             : }
     984             : 
     985             : }  // namespace double_conversion

Generated by: LCOV version 1.13