00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <climits>
00029 #include <cmath>
00030
00031 #include "double-conversion.h"
00032
00033 #include "bignum-dtoa.h"
00034 #include "fast-dtoa.h"
00035 #include "fixed-dtoa.h"
00036 #include "ieee.h"
00037 #include "strtod.h"
00038 #include "utils.h"
00039
00040 namespace double_conversion {
00041
00042 const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
00043 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
00044 static DoubleToStringConverter converter(flags,
00045 "Infinity",
00046 "NaN",
00047 'e',
00048 -6, 21,
00049 6, 0);
00050 return converter;
00051 }
00052
00053
00054 bool DoubleToStringConverter::HandleSpecialValues(
00055 double value,
00056 StringBuilder* result_builder) const {
00057 Double double_inspect(value);
00058 if (double_inspect.IsInfinite()) {
00059 if (infinity_symbol_ == NULL) return false;
00060 if (value < 0) {
00061 result_builder->AddCharacter('-');
00062 }
00063 result_builder->AddString(infinity_symbol_);
00064 return true;
00065 }
00066 if (double_inspect.IsNan()) {
00067 if (nan_symbol_ == NULL) return false;
00068 result_builder->AddString(nan_symbol_);
00069 return true;
00070 }
00071 return false;
00072 }
00073
00074
00075 void DoubleToStringConverter::CreateExponentialRepresentation(
00076 const char* decimal_digits,
00077 int length,
00078 int exponent,
00079 StringBuilder* result_builder) const {
00080 ASSERT(length != 0);
00081 result_builder->AddCharacter(decimal_digits[0]);
00082 if (length != 1) {
00083 result_builder->AddCharacter('.');
00084 result_builder->AddSubstring(&decimal_digits[1], length-1);
00085 }
00086 result_builder->AddCharacter(exponent_character_);
00087 if (exponent < 0) {
00088 result_builder->AddCharacter('-');
00089 exponent = -exponent;
00090 } else {
00091 if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
00092 result_builder->AddCharacter('+');
00093 }
00094 }
00095 if (exponent == 0) {
00096 result_builder->AddCharacter('0');
00097 return;
00098 }
00099 ASSERT(exponent < 1e4);
00100 const int kMaxExponentLength = 5;
00101 char buffer[kMaxExponentLength + 1];
00102 buffer[kMaxExponentLength] = '\0';
00103 int first_char_pos = kMaxExponentLength;
00104 while (exponent > 0) {
00105 buffer[--first_char_pos] = '0' + (exponent % 10);
00106 exponent /= 10;
00107 }
00108 result_builder->AddSubstring(&buffer[first_char_pos],
00109 kMaxExponentLength - first_char_pos);
00110 }
00111
00112
00113 void DoubleToStringConverter::CreateDecimalRepresentation(
00114 const char* decimal_digits,
00115 int length,
00116 int decimal_point,
00117 int digits_after_point,
00118 StringBuilder* result_builder) const {
00119
00120 if (decimal_point <= 0) {
00121
00122 result_builder->AddCharacter('0');
00123 if (digits_after_point > 0) {
00124 result_builder->AddCharacter('.');
00125 result_builder->AddPadding('0', -decimal_point);
00126 ASSERT(length <= digits_after_point - (-decimal_point));
00127 result_builder->AddSubstring(decimal_digits, length);
00128 int remaining_digits = digits_after_point - (-decimal_point) - length;
00129 result_builder->AddPadding('0', remaining_digits);
00130 }
00131 } else if (decimal_point >= length) {
00132
00133 result_builder->AddSubstring(decimal_digits, length);
00134 result_builder->AddPadding('0', decimal_point - length);
00135 if (digits_after_point > 0) {
00136 result_builder->AddCharacter('.');
00137 result_builder->AddPadding('0', digits_after_point);
00138 }
00139 } else {
00140
00141 ASSERT(digits_after_point > 0);
00142 result_builder->AddSubstring(decimal_digits, decimal_point);
00143 result_builder->AddCharacter('.');
00144 ASSERT(length - decimal_point <= digits_after_point);
00145 result_builder->AddSubstring(&decimal_digits[decimal_point],
00146 length - decimal_point);
00147 int remaining_digits = digits_after_point - (length - decimal_point);
00148 result_builder->AddPadding('0', remaining_digits);
00149 }
00150 if (digits_after_point == 0) {
00151 if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
00152 result_builder->AddCharacter('.');
00153 }
00154 if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
00155 result_builder->AddCharacter('0');
00156 }
00157 }
00158 }
00159
00160
00161 bool DoubleToStringConverter::ToShortestIeeeNumber(
00162 double value,
00163 StringBuilder* result_builder,
00164 DoubleToStringConverter::DtoaMode mode) const {
00165 ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
00166 if (Double(value).IsSpecial()) {
00167 return HandleSpecialValues(value, result_builder);
00168 }
00169
00170 int decimal_point;
00171 bool sign;
00172 const int kDecimalRepCapacity = kBase10MaximalLength + 1;
00173 char decimal_rep[kDecimalRepCapacity];
00174 int decimal_rep_length;
00175
00176 DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
00177 &sign, &decimal_rep_length, &decimal_point);
00178
00179 bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
00180 if (sign && (value != 0.0 || !unique_zero)) {
00181 result_builder->AddCharacter('-');
00182 }
00183
00184 int exponent = decimal_point - 1;
00185 if ((decimal_in_shortest_low_ <= exponent) &&
00186 (exponent < decimal_in_shortest_high_)) {
00187 CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
00188 decimal_point,
00189 Max(0, decimal_rep_length - decimal_point),
00190 result_builder);
00191 } else {
00192 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
00193 result_builder);
00194 }
00195 return true;
00196 }
00197
00198
00199 bool DoubleToStringConverter::ToFixed(double value,
00200 int requested_digits,
00201 StringBuilder* result_builder) const {
00202 ASSERT(kMaxFixedDigitsBeforePoint == 60);
00203 const double kFirstNonFixed = 1e60;
00204
00205 if (Double(value).IsSpecial()) {
00206 return HandleSpecialValues(value, result_builder);
00207 }
00208
00209 if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
00210 if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
00211
00212
00213 int decimal_point;
00214 bool sign;
00215
00216 const int kDecimalRepCapacity =
00217 kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
00218 char decimal_rep[kDecimalRepCapacity];
00219 int decimal_rep_length;
00220 DoubleToAscii(value, FIXED, requested_digits,
00221 decimal_rep, kDecimalRepCapacity,
00222 &sign, &decimal_rep_length, &decimal_point);
00223
00224 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
00225 if (sign && (value != 0.0 || !unique_zero)) {
00226 result_builder->AddCharacter('-');
00227 }
00228
00229 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
00230 requested_digits, result_builder);
00231 return true;
00232 }
00233
00234
00235 bool DoubleToStringConverter::ToExponential(
00236 double value,
00237 int requested_digits,
00238 StringBuilder* result_builder) const {
00239 if (Double(value).IsSpecial()) {
00240 return HandleSpecialValues(value, result_builder);
00241 }
00242
00243 if (requested_digits < -1) return false;
00244 if (requested_digits > kMaxExponentialDigits) return false;
00245
00246 int decimal_point;
00247 bool sign;
00248
00249 const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
00250 ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
00251 char decimal_rep[kDecimalRepCapacity];
00252 int decimal_rep_length;
00253
00254 if (requested_digits == -1) {
00255 DoubleToAscii(value, SHORTEST, 0,
00256 decimal_rep, kDecimalRepCapacity,
00257 &sign, &decimal_rep_length, &decimal_point);
00258 } else {
00259 DoubleToAscii(value, PRECISION, requested_digits + 1,
00260 decimal_rep, kDecimalRepCapacity,
00261 &sign, &decimal_rep_length, &decimal_point);
00262 ASSERT(decimal_rep_length <= requested_digits + 1);
00263
00264 for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
00265 decimal_rep[i] = '0';
00266 }
00267 decimal_rep_length = requested_digits + 1;
00268 }
00269
00270 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
00271 if (sign && (value != 0.0 || !unique_zero)) {
00272 result_builder->AddCharacter('-');
00273 }
00274
00275 int exponent = decimal_point - 1;
00276 CreateExponentialRepresentation(decimal_rep,
00277 decimal_rep_length,
00278 exponent,
00279 result_builder);
00280 return true;
00281 }
00282
00283
00284 bool DoubleToStringConverter::ToPrecision(double value,
00285 int precision,
00286 StringBuilder* result_builder) const {
00287 if (Double(value).IsSpecial()) {
00288 return HandleSpecialValues(value, result_builder);
00289 }
00290
00291 if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
00292 return false;
00293 }
00294
00295
00296 int decimal_point;
00297 bool sign;
00298
00299 const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
00300 char decimal_rep[kDecimalRepCapacity];
00301 int decimal_rep_length;
00302
00303 DoubleToAscii(value, PRECISION, precision,
00304 decimal_rep, kDecimalRepCapacity,
00305 &sign, &decimal_rep_length, &decimal_point);
00306 ASSERT(decimal_rep_length <= precision);
00307
00308 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
00309 if (sign && (value != 0.0 || !unique_zero)) {
00310 result_builder->AddCharacter('-');
00311 }
00312
00313
00314
00315 int exponent = decimal_point - 1;
00316
00317 int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
00318 if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
00319 (decimal_point - precision + extra_zero >
00320 max_trailing_padding_zeroes_in_precision_mode_)) {
00321
00322
00323
00324 for (int i = decimal_rep_length; i < precision; ++i) {
00325 decimal_rep[i] = '0';
00326 }
00327
00328 CreateExponentialRepresentation(decimal_rep,
00329 precision,
00330 exponent,
00331 result_builder);
00332 } else {
00333 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
00334 Max(0, precision - decimal_point),
00335 result_builder);
00336 }
00337 return true;
00338 }
00339
00340
00341 static BignumDtoaMode DtoaToBignumDtoaMode(
00342 DoubleToStringConverter::DtoaMode dtoa_mode) {
00343 switch (dtoa_mode) {
00344 case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
00345 case DoubleToStringConverter::SHORTEST_SINGLE:
00346 return BIGNUM_DTOA_SHORTEST_SINGLE;
00347 case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
00348 case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
00349 default:
00350 UNREACHABLE();
00351 return BIGNUM_DTOA_SHORTEST;
00352 }
00353 }
00354
00355
00356 void DoubleToStringConverter::DoubleToAscii(double v,
00357 DtoaMode mode,
00358 int requested_digits,
00359 char* buffer,
00360 int buffer_length,
00361 bool* sign,
00362 int* length,
00363 int* point) {
00364 Vector<char> vector(buffer, buffer_length);
00365 ASSERT(!Double(v).IsSpecial());
00366 ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
00367
00368 if (Double(v).Sign() < 0) {
00369 *sign = true;
00370 v = -v;
00371 } else {
00372 *sign = false;
00373 }
00374
00375 if (mode == PRECISION && requested_digits == 0) {
00376 vector[0] = '\0';
00377 *length = 0;
00378 return;
00379 }
00380
00381 if (v == 0) {
00382 vector[0] = '0';
00383 vector[1] = '\0';
00384 *length = 1;
00385 *point = 1;
00386 return;
00387 }
00388
00389 bool fast_worked;
00390 switch (mode) {
00391 case SHORTEST:
00392 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
00393 break;
00394 case SHORTEST_SINGLE:
00395 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
00396 vector, length, point);
00397 break;
00398 case FIXED:
00399 fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
00400 break;
00401 case PRECISION:
00402 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
00403 vector, length, point);
00404 break;
00405 default:
00406 UNREACHABLE();
00407 fast_worked = false;
00408 }
00409 if (fast_worked) return;
00410
00411
00412 BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
00413 BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
00414 vector[*length] = '\0';
00415 }
00416
00417
00418
00419
00420 static bool ConsumeSubString(const char** current,
00421 const char* end,
00422 const char* substring) {
00423 ASSERT(**current == *substring);
00424 for (substring++; *substring != '\0'; substring++) {
00425 ++*current;
00426 if (*current == end || **current != *substring) return false;
00427 }
00428 ++*current;
00429 return true;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 const int kMaxSignificantDigits = 772;
00441
00442
00443
00444 static inline bool AdvanceToNonspace(const char** current, const char* end) {
00445 while (*current != end) {
00446 if (**current != ' ') return true;
00447 ++*current;
00448 }
00449 return false;
00450 }
00451
00452
00453 static bool isDigit(int x, int radix) {
00454 return (x >= '0' && x <= '9' && x < '0' + radix)
00455 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
00456 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
00457 }
00458
00459
00460 static double SignedZero(bool sign) {
00461 return sign ? -0.0 : 0.0;
00462 }
00463
00464
00465
00466 template <int radix_log_2>
00467 static double RadixStringToIeee(const char* current,
00468 const char* end,
00469 bool sign,
00470 bool allow_trailing_junk,
00471 double junk_string_value,
00472 bool read_as_double,
00473 const char** trailing_pointer) {
00474 ASSERT(current != end);
00475
00476 const int kDoubleSize = Double::kSignificandSize;
00477 const int kSingleSize = Single::kSignificandSize;
00478 const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
00479
00480
00481 while (*current == '0') {
00482 ++current;
00483 if (current == end) {
00484 *trailing_pointer = end;
00485 return SignedZero(sign);
00486 }
00487 }
00488
00489 int64_t number = 0;
00490 int exponent = 0;
00491 const int radix = (1 << radix_log_2);
00492
00493 do {
00494 int digit;
00495 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
00496 digit = static_cast<char>(*current) - '0';
00497 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
00498 digit = static_cast<char>(*current) - 'a' + 10;
00499 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
00500 digit = static_cast<char>(*current) - 'A' + 10;
00501 } else {
00502 if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) {
00503 break;
00504 } else {
00505 return junk_string_value;
00506 }
00507 }
00508
00509 number = number * radix + digit;
00510 int overflow = static_cast<int>(number >> kSignificandSize);
00511 if (overflow != 0) {
00512
00513
00514 int overflow_bits_count = 1;
00515 while (overflow > 1) {
00516 overflow_bits_count++;
00517 overflow >>= 1;
00518 }
00519
00520 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
00521 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
00522 number >>= overflow_bits_count;
00523 exponent = overflow_bits_count;
00524
00525 bool zero_tail = true;
00526 while (true) {
00527 ++current;
00528 if (current == end || !isDigit(*current, radix)) break;
00529 zero_tail = zero_tail && *current == '0';
00530 exponent += radix_log_2;
00531 }
00532
00533 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
00534 return junk_string_value;
00535 }
00536
00537 int middle_value = (1 << (overflow_bits_count - 1));
00538 if (dropped_bits > middle_value) {
00539 number++;
00540 } else if (dropped_bits == middle_value) {
00541
00542
00543 if ((number & 1) != 0 || !zero_tail) {
00544 number++;
00545 }
00546 }
00547
00548
00549 if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
00550 exponent++;
00551 number >>= 1;
00552 }
00553 break;
00554 }
00555 ++current;
00556 } while (current != end);
00557
00558 ASSERT(number < ((int64_t)1 << kSignificandSize));
00559 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
00560
00561 *trailing_pointer = current;
00562
00563 if (exponent == 0) {
00564 if (sign) {
00565 if (number == 0) return -0.0;
00566 number = -number;
00567 }
00568 return static_cast<double>(number);
00569 }
00570
00571 ASSERT(number != 0);
00572 return Double(DiyFp(number, exponent)).value();
00573 }
00574
00575
00576 double StringToDoubleConverter::StringToIeee(
00577 const char* input,
00578 int length,
00579 int* processed_characters_count,
00580 bool read_as_double) const {
00581 const char* current = input;
00582 const char* end = input + length;
00583
00584 *processed_characters_count = 0;
00585
00586 const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
00587 const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
00588 const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
00589 const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 if (current == end) return empty_string_value_;
00600
00601 if (allow_leading_spaces || allow_trailing_spaces) {
00602 if (!AdvanceToNonspace(¤t, end)) {
00603 *processed_characters_count = current - input;
00604 return empty_string_value_;
00605 }
00606 if (!allow_leading_spaces && (input != current)) {
00607
00608 return junk_string_value_;
00609 }
00610 }
00611
00612
00613 const int kBufferSize = kMaxSignificantDigits + 10;
00614 char buffer[kBufferSize];
00615 int buffer_pos = 0;
00616
00617
00618
00619 int exponent = 0;
00620 int significant_digits = 0;
00621 int insignificant_digits = 0;
00622 bool nonzero_digit_dropped = false;
00623
00624 bool sign = false;
00625
00626 if (*current == '+' || *current == '-') {
00627 sign = (*current == '-');
00628 ++current;
00629 const char* next_non_space = current;
00630
00631 if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
00632 if (!allow_spaces_after_sign && (current != next_non_space)) {
00633 return junk_string_value_;
00634 }
00635 current = next_non_space;
00636 }
00637
00638 if (infinity_symbol_ != NULL) {
00639 if (*current == infinity_symbol_[0]) {
00640 if (!ConsumeSubString(¤t, end, infinity_symbol_)) {
00641 return junk_string_value_;
00642 }
00643
00644 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
00645 return junk_string_value_;
00646 }
00647 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
00648 return junk_string_value_;
00649 }
00650
00651 ASSERT(buffer_pos == 0);
00652 *processed_characters_count = current - input;
00653 return sign ? -Double::Infinity() : Double::Infinity();
00654 }
00655 }
00656
00657 if (nan_symbol_ != NULL) {
00658 if (*current == nan_symbol_[0]) {
00659 if (!ConsumeSubString(¤t, end, nan_symbol_)) {
00660 return junk_string_value_;
00661 }
00662
00663 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
00664 return junk_string_value_;
00665 }
00666 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
00667 return junk_string_value_;
00668 }
00669
00670 ASSERT(buffer_pos == 0);
00671 *processed_characters_count = current - input;
00672 return sign ? -Double::NaN() : Double::NaN();
00673 }
00674 }
00675
00676 bool leading_zero = false;
00677 if (*current == '0') {
00678 ++current;
00679 if (current == end) {
00680 *processed_characters_count = current - input;
00681 return SignedZero(sign);
00682 }
00683
00684 leading_zero = true;
00685
00686
00687 if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
00688 ++current;
00689 if (current == end || !isDigit(*current, 16)) {
00690 return junk_string_value_;
00691 }
00692
00693 const char* tail_pointer = NULL;
00694 double result = RadixStringToIeee<4>(current,
00695 end,
00696 sign,
00697 allow_trailing_junk,
00698 junk_string_value_,
00699 read_as_double,
00700 &tail_pointer);
00701 if (tail_pointer != NULL) {
00702 if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
00703 *processed_characters_count = tail_pointer - input;
00704 }
00705 return result;
00706 }
00707
00708
00709 while (*current == '0') {
00710 ++current;
00711 if (current == end) {
00712 *processed_characters_count = current - input;
00713 return SignedZero(sign);
00714 }
00715 }
00716 }
00717
00718 bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
00719
00720
00721 while (*current >= '0' && *current <= '9') {
00722 if (significant_digits < kMaxSignificantDigits) {
00723 ASSERT(buffer_pos < kBufferSize);
00724 buffer[buffer_pos++] = static_cast<char>(*current);
00725 significant_digits++;
00726
00727 } else {
00728 insignificant_digits++;
00729 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
00730 }
00731 octal = octal && *current < '8';
00732 ++current;
00733 if (current == end) goto parsing_done;
00734 }
00735
00736 if (significant_digits == 0) {
00737 octal = false;
00738 }
00739
00740 if (*current == '.') {
00741 if (octal && !allow_trailing_junk) return junk_string_value_;
00742 if (octal) goto parsing_done;
00743
00744 ++current;
00745 if (current == end) {
00746 if (significant_digits == 0 && !leading_zero) {
00747 return junk_string_value_;
00748 } else {
00749 goto parsing_done;
00750 }
00751 }
00752
00753 if (significant_digits == 0) {
00754
00755
00756
00757 while (*current == '0') {
00758 ++current;
00759 if (current == end) {
00760 *processed_characters_count = current - input;
00761 return SignedZero(sign);
00762 }
00763 exponent--;
00764 }
00765 }
00766
00767
00768
00769 while (*current >= '0' && *current <= '9') {
00770 if (significant_digits < kMaxSignificantDigits) {
00771 ASSERT(buffer_pos < kBufferSize);
00772 buffer[buffer_pos++] = static_cast<char>(*current);
00773 significant_digits++;
00774 exponent--;
00775 } else {
00776
00777 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
00778 }
00779 ++current;
00780 if (current == end) goto parsing_done;
00781 }
00782 }
00783
00784 if (!leading_zero && exponent == 0 && significant_digits == 0) {
00785
00786
00787
00788
00789 return junk_string_value_;
00790 }
00791
00792
00793 if (*current == 'e' || *current == 'E') {
00794 if (octal && !allow_trailing_junk) return junk_string_value_;
00795 if (octal) goto parsing_done;
00796 ++current;
00797 if (current == end) {
00798 if (allow_trailing_junk) {
00799 goto parsing_done;
00800 } else {
00801 return junk_string_value_;
00802 }
00803 }
00804 char sign = '+';
00805 if (*current == '+' || *current == '-') {
00806 sign = static_cast<char>(*current);
00807 ++current;
00808 if (current == end) {
00809 if (allow_trailing_junk) {
00810 goto parsing_done;
00811 } else {
00812 return junk_string_value_;
00813 }
00814 }
00815 }
00816
00817 if (current == end || *current < '0' || *current > '9') {
00818 if (allow_trailing_junk) {
00819 goto parsing_done;
00820 } else {
00821 return junk_string_value_;
00822 }
00823 }
00824
00825 const int max_exponent = INT_MAX / 2;
00826 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
00827 int num = 0;
00828 do {
00829
00830 int digit = *current - '0';
00831 if (num >= max_exponent / 10
00832 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
00833 num = max_exponent;
00834 } else {
00835 num = num * 10 + digit;
00836 }
00837 ++current;
00838 } while (current != end && *current >= '0' && *current <= '9');
00839
00840 exponent += (sign == '-' ? -num : num);
00841 }
00842
00843 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
00844 return junk_string_value_;
00845 }
00846 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
00847 return junk_string_value_;
00848 }
00849 if (allow_trailing_spaces) {
00850 AdvanceToNonspace(¤t, end);
00851 }
00852
00853 parsing_done:
00854 exponent += insignificant_digits;
00855
00856 if (octal) {
00857 double result;
00858 const char* tail_pointer = NULL;
00859 result = RadixStringToIeee<3>(buffer,
00860 buffer + buffer_pos,
00861 sign,
00862 allow_trailing_junk,
00863 junk_string_value_,
00864 read_as_double,
00865 &tail_pointer);
00866 ASSERT(tail_pointer != NULL);
00867 *processed_characters_count = current - input;
00868 return result;
00869 }
00870
00871 if (nonzero_digit_dropped) {
00872 buffer[buffer_pos++] = '1';
00873 exponent--;
00874 }
00875
00876 ASSERT(buffer_pos < kBufferSize);
00877 buffer[buffer_pos] = '\0';
00878
00879 double converted;
00880 if (read_as_double) {
00881 converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
00882 } else {
00883 converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
00884 }
00885 *processed_characters_count = current - input;
00886 return sign? -converted: converted;
00887 }
00888
00889 }