| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 // must be rounded to the bigger one unless the tail consists of zeros, so | 113 // must be rounded to the bigger one unless the tail consists of zeros, so |
| 114 // we don't need to preserve all the digits. | 114 // we don't need to preserve all the digits. |
| 115 const int kMaxSignificantDigits = 772; | 115 const int kMaxSignificantDigits = 772; |
| 116 | 116 |
| 117 | 117 |
| 118 static const double JUNK_STRING_VALUE = OS::nan_value(); | 118 static const double JUNK_STRING_VALUE = OS::nan_value(); |
| 119 | 119 |
| 120 | 120 |
| 121 // Returns true if a nonspace found and false if the end has reached. | 121 // Returns true if a nonspace found and false if the end has reached. |
| 122 template <class Iterator, class EndMark> | 122 template <class Iterator, class EndMark> |
| 123 static inline bool AdvanceToNonspace(Iterator* current, EndMark end) { | 123 static inline bool AdvanceToNonspace(ScannerCharacterClasses* character_classes, |
| 124 Iterator* current, |
| 125 EndMark end) { |
| 124 while (*current != end) { | 126 while (*current != end) { |
| 125 if (!Scanner::kIsWhiteSpace.get(**current)) return true; | 127 if (!character_classes->IsWhiteSpace(**current)) return true; |
| 126 ++*current; | 128 ++*current; |
| 127 } | 129 } |
| 128 return false; | 130 return false; |
| 129 } | 131 } |
| 130 | 132 |
| 131 | 133 |
| 132 static bool isDigit(int x, int radix) { | 134 static bool isDigit(int x, int radix) { |
| 133 return (x >= '0' && x <= '9' && x < '0' + radix) | 135 return (x >= '0' && x <= '9' && x < '0' + radix) |
| 134 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) | 136 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) |
| 135 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); | 137 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); |
| 136 } | 138 } |
| 137 | 139 |
| 138 | 140 |
| 139 static double SignedZero(bool sign) { | 141 static double SignedZero(bool sign) { |
| 140 return sign ? -0.0 : 0.0; | 142 return sign ? -0.0 : 0.0; |
| 141 } | 143 } |
| 142 | 144 |
| 143 | 145 |
| 144 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. | 146 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
| 145 template <int radix_log_2, class Iterator, class EndMark> | 147 template <int radix_log_2, class Iterator, class EndMark> |
| 146 static double InternalStringToIntDouble(Iterator current, | 148 static double InternalStringToIntDouble( |
| 147 EndMark end, | 149 ScannerCharacterClasses* character_classes, |
| 148 bool sign, | 150 Iterator current, |
| 149 bool allow_trailing_junk) { | 151 EndMark end, |
| 152 bool sign, |
| 153 bool allow_trailing_junk) { |
| 150 ASSERT(current != end); | 154 ASSERT(current != end); |
| 151 | 155 |
| 152 // Skip leading 0s. | 156 // Skip leading 0s. |
| 153 while (*current == '0') { | 157 while (*current == '0') { |
| 154 ++current; | 158 ++current; |
| 155 if (current == end) return SignedZero(sign); | 159 if (current == end) return SignedZero(sign); |
| 156 } | 160 } |
| 157 | 161 |
| 158 int64_t number = 0; | 162 int64_t number = 0; |
| 159 int exponent = 0; | 163 int exponent = 0; |
| 160 const int radix = (1 << radix_log_2); | 164 const int radix = (1 << radix_log_2); |
| 161 | 165 |
| 162 do { | 166 do { |
| 163 int digit; | 167 int digit; |
| 164 if (*current >= '0' && *current <= '9' && *current < '0' + radix) { | 168 if (*current >= '0' && *current <= '9' && *current < '0' + radix) { |
| 165 digit = static_cast<char>(*current) - '0'; | 169 digit = static_cast<char>(*current) - '0'; |
| 166 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { | 170 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { |
| 167 digit = static_cast<char>(*current) - 'a' + 10; | 171 digit = static_cast<char>(*current) - 'a' + 10; |
| 168 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { | 172 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { |
| 169 digit = static_cast<char>(*current) - 'A' + 10; | 173 digit = static_cast<char>(*current) - 'A' + 10; |
| 170 } else { | 174 } else { |
| 171 if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) { | 175 if (allow_trailing_junk || |
| 176 !AdvanceToNonspace(character_classes, ¤t, end)) { |
| 172 break; | 177 break; |
| 173 } else { | 178 } else { |
| 174 return JUNK_STRING_VALUE; | 179 return JUNK_STRING_VALUE; |
| 175 } | 180 } |
| 176 } | 181 } |
| 177 | 182 |
| 178 number = number * radix + digit; | 183 number = number * radix + digit; |
| 179 int overflow = static_cast<int>(number >> 53); | 184 int overflow = static_cast<int>(number >> 53); |
| 180 if (overflow != 0) { | 185 if (overflow != 0) { |
| 181 // Overflow occurred. Need to determine which direction to round the | 186 // Overflow occurred. Need to determine which direction to round the |
| (...skipping 10 matching lines...) Expand all Loading... |
| 192 exponent = overflow_bits_count; | 197 exponent = overflow_bits_count; |
| 193 | 198 |
| 194 bool zero_tail = true; | 199 bool zero_tail = true; |
| 195 while (true) { | 200 while (true) { |
| 196 ++current; | 201 ++current; |
| 197 if (current == end || !isDigit(*current, radix)) break; | 202 if (current == end || !isDigit(*current, radix)) break; |
| 198 zero_tail = zero_tail && *current == '0'; | 203 zero_tail = zero_tail && *current == '0'; |
| 199 exponent += radix_log_2; | 204 exponent += radix_log_2; |
| 200 } | 205 } |
| 201 | 206 |
| 202 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 207 if (!allow_trailing_junk && |
| 208 AdvanceToNonspace(character_classes, ¤t, end)) { |
| 203 return JUNK_STRING_VALUE; | 209 return JUNK_STRING_VALUE; |
| 204 } | 210 } |
| 205 | 211 |
| 206 int middle_value = (1 << (overflow_bits_count - 1)); | 212 int middle_value = (1 << (overflow_bits_count - 1)); |
| 207 if (dropped_bits > middle_value) { | 213 if (dropped_bits > middle_value) { |
| 208 number++; // Rounding up. | 214 number++; // Rounding up. |
| 209 } else if (dropped_bits == middle_value) { | 215 } else if (dropped_bits == middle_value) { |
| 210 // Rounding to even to consistency with decimals: half-way case rounds | 216 // Rounding to even to consistency with decimals: half-way case rounds |
| 211 // up if significant part is odd and down otherwise. | 217 // up if significant part is odd and down otherwise. |
| 212 if ((number & 1) != 0 || !zero_tail) { | 218 if ((number & 1) != 0 || !zero_tail) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 236 } | 242 } |
| 237 | 243 |
| 238 ASSERT(number != 0); | 244 ASSERT(number != 0); |
| 239 // The double could be constructed faster from number (mantissa), exponent | 245 // The double could be constructed faster from number (mantissa), exponent |
| 240 // and sign. Assuming it's a rare case more simple code is used. | 246 // and sign. Assuming it's a rare case more simple code is used. |
| 241 return static_cast<double>(sign ? -number : number) * pow(2.0, exponent); | 247 return static_cast<double>(sign ? -number : number) * pow(2.0, exponent); |
| 242 } | 248 } |
| 243 | 249 |
| 244 | 250 |
| 245 template <class Iterator, class EndMark> | 251 template <class Iterator, class EndMark> |
| 246 static double InternalStringToInt(Iterator current, EndMark end, int radix) { | 252 static double InternalStringToInt(ScannerCharacterClasses* character_classes, |
| 253 Iterator current, |
| 254 EndMark end, |
| 255 int radix) { |
| 247 const bool allow_trailing_junk = true; | 256 const bool allow_trailing_junk = true; |
| 248 const double empty_string_val = JUNK_STRING_VALUE; | 257 const double empty_string_val = JUNK_STRING_VALUE; |
| 249 | 258 |
| 250 if (!AdvanceToNonspace(¤t, end)) return empty_string_val; | 259 if (!AdvanceToNonspace(character_classes, ¤t, end)) { |
| 260 return empty_string_val; |
| 261 } |
| 251 | 262 |
| 252 bool sign = false; | 263 bool sign = false; |
| 253 bool leading_zero = false; | 264 bool leading_zero = false; |
| 254 | 265 |
| 255 if (*current == '+') { | 266 if (*current == '+') { |
| 256 // Ignore leading sign; skip following spaces. | 267 // Ignore leading sign; skip following spaces. |
| 257 ++current; | 268 ++current; |
| 258 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 269 if (!AdvanceToNonspace(character_classes, ¤t, end)) { |
| 270 return JUNK_STRING_VALUE; |
| 271 } |
| 259 } else if (*current == '-') { | 272 } else if (*current == '-') { |
| 260 ++current; | 273 ++current; |
| 261 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 274 if (!AdvanceToNonspace(character_classes, ¤t, end)) { |
| 275 return JUNK_STRING_VALUE; |
| 276 } |
| 262 sign = true; | 277 sign = true; |
| 263 } | 278 } |
| 264 | 279 |
| 265 if (radix == 0) { | 280 if (radix == 0) { |
| 266 // Radix detection. | 281 // Radix detection. |
| 267 if (*current == '0') { | 282 if (*current == '0') { |
| 268 ++current; | 283 ++current; |
| 269 if (current == end) return SignedZero(sign); | 284 if (current == end) return SignedZero(sign); |
| 270 if (*current == 'x' || *current == 'X') { | 285 if (*current == 'x' || *current == 'X') { |
| 271 radix = 16; | 286 radix = 16; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 302 } | 317 } |
| 303 | 318 |
| 304 if (!leading_zero && !isDigit(*current, radix)) { | 319 if (!leading_zero && !isDigit(*current, radix)) { |
| 305 return JUNK_STRING_VALUE; | 320 return JUNK_STRING_VALUE; |
| 306 } | 321 } |
| 307 | 322 |
| 308 if (IsPowerOf2(radix)) { | 323 if (IsPowerOf2(radix)) { |
| 309 switch (radix) { | 324 switch (radix) { |
| 310 case 2: | 325 case 2: |
| 311 return InternalStringToIntDouble<1>( | 326 return InternalStringToIntDouble<1>( |
| 312 current, end, sign, allow_trailing_junk); | 327 character_classes, current, end, sign, allow_trailing_junk); |
| 313 case 4: | 328 case 4: |
| 314 return InternalStringToIntDouble<2>( | 329 return InternalStringToIntDouble<2>( |
| 315 current, end, sign, allow_trailing_junk); | 330 character_classes, current, end, sign, allow_trailing_junk); |
| 316 case 8: | 331 case 8: |
| 317 return InternalStringToIntDouble<3>( | 332 return InternalStringToIntDouble<3>( |
| 318 current, end, sign, allow_trailing_junk); | 333 character_classes, current, end, sign, allow_trailing_junk); |
| 319 | 334 |
| 320 case 16: | 335 case 16: |
| 321 return InternalStringToIntDouble<4>( | 336 return InternalStringToIntDouble<4>( |
| 322 current, end, sign, allow_trailing_junk); | 337 character_classes, current, end, sign, allow_trailing_junk); |
| 323 | 338 |
| 324 case 32: | 339 case 32: |
| 325 return InternalStringToIntDouble<5>( | 340 return InternalStringToIntDouble<5>( |
| 326 current, end, sign, allow_trailing_junk); | 341 character_classes, current, end, sign, allow_trailing_junk); |
| 327 default: | 342 default: |
| 328 UNREACHABLE(); | 343 UNREACHABLE(); |
| 329 } | 344 } |
| 330 } | 345 } |
| 331 | 346 |
| 332 if (radix == 10) { | 347 if (radix == 10) { |
| 333 // Parsing with strtod. | 348 // Parsing with strtod. |
| 334 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308. | 349 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308. |
| 335 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero | 350 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero |
| 336 // end. | 351 // end. |
| 337 const int kBufferSize = kMaxSignificantDigits + 2; | 352 const int kBufferSize = kMaxSignificantDigits + 2; |
| 338 char buffer[kBufferSize]; | 353 char buffer[kBufferSize]; |
| 339 int buffer_pos = 0; | 354 int buffer_pos = 0; |
| 340 while (*current >= '0' && *current <= '9') { | 355 while (*current >= '0' && *current <= '9') { |
| 341 if (buffer_pos <= kMaxSignificantDigits) { | 356 if (buffer_pos <= kMaxSignificantDigits) { |
| 342 // If the number has more than kMaxSignificantDigits it will be parsed | 357 // If the number has more than kMaxSignificantDigits it will be parsed |
| 343 // as infinity. | 358 // as infinity. |
| 344 ASSERT(buffer_pos < kBufferSize); | 359 ASSERT(buffer_pos < kBufferSize); |
| 345 buffer[buffer_pos++] = static_cast<char>(*current); | 360 buffer[buffer_pos++] = static_cast<char>(*current); |
| 346 } | 361 } |
| 347 ++current; | 362 ++current; |
| 348 if (current == end) break; | 363 if (current == end) break; |
| 349 } | 364 } |
| 350 | 365 |
| 351 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 366 if (!allow_trailing_junk && |
| 367 AdvanceToNonspace(character_classes, ¤t, end)) { |
| 352 return JUNK_STRING_VALUE; | 368 return JUNK_STRING_VALUE; |
| 353 } | 369 } |
| 354 | 370 |
| 355 ASSERT(buffer_pos < kBufferSize); | 371 ASSERT(buffer_pos < kBufferSize); |
| 356 buffer[buffer_pos++] = '\0'; | 372 buffer[buffer_pos++] = '\0'; |
| 357 return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL); | 373 return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL); |
| 358 } | 374 } |
| 359 | 375 |
| 360 // The following code causes accumulating rounding error for numbers greater | 376 // The following code causes accumulating rounding error for numbers greater |
| 361 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, | 377 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 if (current == end) { | 421 if (current == end) { |
| 406 done = true; | 422 done = true; |
| 407 break; | 423 break; |
| 408 } | 424 } |
| 409 } | 425 } |
| 410 | 426 |
| 411 // Update the value and skip the part in the string. | 427 // Update the value and skip the part in the string. |
| 412 v = v * multiplier + part; | 428 v = v * multiplier + part; |
| 413 } while (!done); | 429 } while (!done); |
| 414 | 430 |
| 415 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 431 if (!allow_trailing_junk && |
| 432 AdvanceToNonspace(character_classes, ¤t, end)) { |
| 416 return JUNK_STRING_VALUE; | 433 return JUNK_STRING_VALUE; |
| 417 } | 434 } |
| 418 | 435 |
| 419 return sign ? -v : v; | 436 return sign ? -v : v; |
| 420 } | 437 } |
| 421 | 438 |
| 422 | 439 |
| 423 // Converts a string to a double value. Assumes the Iterator supports | 440 // Converts a string to a double value. Assumes the Iterator supports |
| 424 // the following operations: | 441 // the following operations: |
| 425 // 1. current == end (other ops are not allowed), current != end. | 442 // 1. current == end (other ops are not allowed), current != end. |
| 426 // 2. *current - gets the current character in the sequence. | 443 // 2. *current - gets the current character in the sequence. |
| 427 // 3. ++current (advances the position). | 444 // 3. ++current (advances the position). |
| 428 template <class Iterator, class EndMark> | 445 template <class Iterator, class EndMark> |
| 429 static double InternalStringToDouble(Iterator current, | 446 static double InternalStringToDouble(ScannerCharacterClasses* character_classes, |
| 447 Iterator current, |
| 430 EndMark end, | 448 EndMark end, |
| 431 int flags, | 449 int flags, |
| 432 double empty_string_val) { | 450 double empty_string_val) { |
| 433 // To make sure that iterator dereferencing is valid the following | 451 // To make sure that iterator dereferencing is valid the following |
| 434 // convention is used: | 452 // convention is used: |
| 435 // 1. Each '++current' statement is followed by check for equality to 'end'. | 453 // 1. Each '++current' statement is followed by check for equality to 'end'. |
| 436 // 2. If AdvanceToNonspace returned false then current == end. | 454 // 2. If AdvanceToNonspace returned false then current == end. |
| 437 // 3. If 'current' becomes be equal to 'end' the function returns or goes to | 455 // 3. If 'current' becomes be equal to 'end' the function returns or goes to |
| 438 // 'parsing_done'. | 456 // 'parsing_done'. |
| 439 // 4. 'current' is not dereferenced after the 'parsing_done' label. | 457 // 4. 'current' is not dereferenced after the 'parsing_done' label. |
| 440 // 5. Code before 'parsing_done' may rely on 'current != end'. | 458 // 5. Code before 'parsing_done' may rely on 'current != end'. |
| 441 if (!AdvanceToNonspace(¤t, end)) return empty_string_val; | 459 if (!AdvanceToNonspace(character_classes, ¤t, end)) { |
| 460 return empty_string_val; |
| 461 } |
| 442 | 462 |
| 443 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0; | 463 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0; |
| 444 | 464 |
| 445 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0". | 465 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0". |
| 446 const int kBufferSize = kMaxSignificantDigits + 10; | 466 const int kBufferSize = kMaxSignificantDigits + 10; |
| 447 char buffer[kBufferSize]; // NOLINT: size is known at compile time. | 467 char buffer[kBufferSize]; // NOLINT: size is known at compile time. |
| 448 int buffer_pos = 0; | 468 int buffer_pos = 0; |
| 449 | 469 |
| 450 // Exponent will be adjusted if insignificant digits of the integer part | 470 // Exponent will be adjusted if insignificant digits of the integer part |
| 451 // or insignificant leading zeros of the fractional part are dropped. | 471 // or insignificant leading zeros of the fractional part are dropped. |
| 452 int exponent = 0; | 472 int exponent = 0; |
| 453 int significant_digits = 0; | 473 int significant_digits = 0; |
| 454 int insignificant_digits = 0; | 474 int insignificant_digits = 0; |
| 455 bool nonzero_digit_dropped = false; | 475 bool nonzero_digit_dropped = false; |
| 456 bool fractional_part = false; | 476 bool fractional_part = false; |
| 457 | 477 |
| 458 bool sign = false; | 478 bool sign = false; |
| 459 | 479 |
| 460 if (*current == '+') { | 480 if (*current == '+') { |
| 461 // Ignore leading sign; skip following spaces. | 481 // Ignore leading sign; skip following spaces. |
| 462 ++current; | 482 ++current; |
| 463 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 483 if (!AdvanceToNonspace(character_classes, ¤t, end)) { |
| 484 return JUNK_STRING_VALUE; |
| 485 } |
| 464 } else if (*current == '-') { | 486 } else if (*current == '-') { |
| 465 buffer[buffer_pos++] = '-'; | 487 buffer[buffer_pos++] = '-'; |
| 466 ++current; | 488 ++current; |
| 467 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 489 if (!AdvanceToNonspace(character_classes, ¤t, end)) { |
| 490 return JUNK_STRING_VALUE; |
| 491 } |
| 468 sign = true; | 492 sign = true; |
| 469 } | 493 } |
| 470 | 494 |
| 471 static const char kInfinitySymbol[] = "Infinity"; | 495 static const char kInfinitySymbol[] = "Infinity"; |
| 472 if (*current == kInfinitySymbol[0]) { | 496 if (*current == kInfinitySymbol[0]) { |
| 473 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { | 497 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { |
| 474 return JUNK_STRING_VALUE; | 498 return JUNK_STRING_VALUE; |
| 475 } | 499 } |
| 476 | 500 |
| 477 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 501 if (!allow_trailing_junk && |
| 502 AdvanceToNonspace(character_classes, ¤t, end)) { |
| 478 return JUNK_STRING_VALUE; | 503 return JUNK_STRING_VALUE; |
| 479 } | 504 } |
| 480 | 505 |
| 481 ASSERT(buffer_pos == 0 || buffer[0] == '-'); | 506 ASSERT(buffer_pos == 0 || buffer[0] == '-'); |
| 482 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; | 507 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; |
| 483 } | 508 } |
| 484 | 509 |
| 485 bool leading_zero = false; | 510 bool leading_zero = false; |
| 486 if (*current == '0') { | 511 if (*current == '0') { |
| 487 ++current; | 512 ++current; |
| 488 if (current == end) return SignedZero(sign); | 513 if (current == end) return SignedZero(sign); |
| 489 | 514 |
| 490 leading_zero = true; | 515 leading_zero = true; |
| 491 | 516 |
| 492 // It could be hexadecimal value. | 517 // It could be hexadecimal value. |
| 493 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { | 518 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { |
| 494 ++current; | 519 ++current; |
| 495 if (current == end || !isDigit(*current, 16)) { | 520 if (current == end || !isDigit(*current, 16)) { |
| 496 return JUNK_STRING_VALUE; // "0x". | 521 return JUNK_STRING_VALUE; // "0x". |
| 497 } | 522 } |
| 498 | 523 |
| 499 bool sign = (buffer_pos > 0 && buffer[0] == '-'); | 524 bool sign = (buffer_pos > 0 && buffer[0] == '-'); |
| 500 return InternalStringToIntDouble<4>(current, | 525 return InternalStringToIntDouble<4>(character_classes, |
| 526 current, |
| 501 end, | 527 end, |
| 502 sign, | 528 sign, |
| 503 allow_trailing_junk); | 529 allow_trailing_junk); |
| 504 } | 530 } |
| 505 | 531 |
| 506 // Ignore leading zeros in the integer part. | 532 // Ignore leading zeros in the integer part. |
| 507 while (*current == '0') { | 533 while (*current == '0') { |
| 508 ++current; | 534 ++current; |
| 509 if (current == end) return SignedZero(sign); | 535 if (current == end) return SignedZero(sign); |
| 510 } | 536 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 num = max_exponent; | 649 num = max_exponent; |
| 624 } else { | 650 } else { |
| 625 num = num * 10 + digit; | 651 num = num * 10 + digit; |
| 626 } | 652 } |
| 627 ++current; | 653 ++current; |
| 628 } while (current != end && *current >= '0' && *current <= '9'); | 654 } while (current != end && *current >= '0' && *current <= '9'); |
| 629 | 655 |
| 630 exponent += (sign == '-' ? -num : num); | 656 exponent += (sign == '-' ? -num : num); |
| 631 } | 657 } |
| 632 | 658 |
| 633 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 659 if (!allow_trailing_junk && |
| 660 AdvanceToNonspace(character_classes, ¤t, end)) { |
| 634 return JUNK_STRING_VALUE; | 661 return JUNK_STRING_VALUE; |
| 635 } | 662 } |
| 636 | 663 |
| 637 parsing_done: | 664 parsing_done: |
| 638 exponent += insignificant_digits; | 665 exponent += insignificant_digits; |
| 639 | 666 |
| 640 if (octal) { | 667 if (octal) { |
| 641 bool sign = buffer[0] == '-'; | 668 bool sign = buffer[0] == '-'; |
| 642 int start_pos = (sign ? 1 : 0); | 669 int start_pos = (sign ? 1 : 0); |
| 643 | 670 |
| 644 return InternalStringToIntDouble<3>(buffer + start_pos, | 671 return InternalStringToIntDouble<3>(character_classes, |
| 672 buffer + start_pos, |
| 645 buffer + buffer_pos, | 673 buffer + buffer_pos, |
| 646 sign, | 674 sign, |
| 647 allow_trailing_junk); | 675 allow_trailing_junk); |
| 648 } | 676 } |
| 649 | 677 |
| 650 if (nonzero_digit_dropped) { | 678 if (nonzero_digit_dropped) { |
| 651 if (insignificant_digits) buffer[buffer_pos++] = '.'; | 679 if (insignificant_digits) buffer[buffer_pos++] = '.'; |
| 652 buffer[buffer_pos++] = '1'; | 680 buffer[buffer_pos++] = '1'; |
| 653 } | 681 } |
| 654 | 682 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 return static_cast<double>(start_pos == 0 ? num : -num); | 714 return static_cast<double>(start_pos == 0 ? num : -num); |
| 687 } | 715 } |
| 688 | 716 |
| 689 ASSERT(buffer_pos < kBufferSize); | 717 ASSERT(buffer_pos < kBufferSize); |
| 690 buffer[buffer_pos] = '\0'; | 718 buffer[buffer_pos] = '\0'; |
| 691 | 719 |
| 692 return gay_strtod(buffer, NULL); | 720 return gay_strtod(buffer, NULL); |
| 693 } | 721 } |
| 694 | 722 |
| 695 double StringToDouble(String* str, int flags, double empty_string_val) { | 723 double StringToDouble(String* str, int flags, double empty_string_val) { |
| 724 ScannerCharacterClasses* character_classes = |
| 725 Isolate::Current()->scanner_character_classes(); |
| 696 StringShape shape(str); | 726 StringShape shape(str); |
| 697 if (shape.IsSequentialAscii()) { | 727 if (shape.IsSequentialAscii()) { |
| 698 const char* begin = SeqAsciiString::cast(str)->GetChars(); | 728 const char* begin = SeqAsciiString::cast(str)->GetChars(); |
| 699 const char* end = begin + str->length(); | 729 const char* end = begin + str->length(); |
| 700 return InternalStringToDouble(begin, end, flags, empty_string_val); | 730 return InternalStringToDouble(character_classes, begin, end, flags, |
| 731 empty_string_val); |
| 701 } else if (shape.IsSequentialTwoByte()) { | 732 } else if (shape.IsSequentialTwoByte()) { |
| 702 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); | 733 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); |
| 703 const uc16* end = begin + str->length(); | 734 const uc16* end = begin + str->length(); |
| 704 return InternalStringToDouble(begin, end, flags, empty_string_val); | 735 return InternalStringToDouble(character_classes, begin, end, flags, |
| 736 empty_string_val); |
| 705 } else { | 737 } else { |
| 706 StringInputBuffer buffer(str); | 738 StringInputBuffer buffer(str); |
| 707 return InternalStringToDouble(StringInputBufferIterator(&buffer), | 739 return InternalStringToDouble(character_classes, |
| 740 StringInputBufferIterator(&buffer), |
| 708 StringInputBufferIterator::EndMarker(), | 741 StringInputBufferIterator::EndMarker(), |
| 709 flags, | 742 flags, |
| 710 empty_string_val); | 743 empty_string_val); |
| 711 } | 744 } |
| 712 } | 745 } |
| 713 | 746 |
| 714 | 747 |
| 715 double StringToInt(String* str, int radix) { | 748 double StringToInt(String* str, int radix) { |
| 749 ScannerCharacterClasses* character_classes = |
| 750 Isolate::Current()->scanner_character_classes(); |
| 716 StringShape shape(str); | 751 StringShape shape(str); |
| 717 if (shape.IsSequentialAscii()) { | 752 if (shape.IsSequentialAscii()) { |
| 718 const char* begin = SeqAsciiString::cast(str)->GetChars(); | 753 const char* begin = SeqAsciiString::cast(str)->GetChars(); |
| 719 const char* end = begin + str->length(); | 754 const char* end = begin + str->length(); |
| 720 return InternalStringToInt(begin, end, radix); | 755 return InternalStringToInt(character_classes, begin, end, radix); |
| 721 } else if (shape.IsSequentialTwoByte()) { | 756 } else if (shape.IsSequentialTwoByte()) { |
| 722 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); | 757 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); |
| 723 const uc16* end = begin + str->length(); | 758 const uc16* end = begin + str->length(); |
| 724 return InternalStringToInt(begin, end, radix); | 759 return InternalStringToInt(character_classes, begin, end, radix); |
| 725 } else { | 760 } else { |
| 726 StringInputBuffer buffer(str); | 761 StringInputBuffer buffer(str); |
| 727 return InternalStringToInt(StringInputBufferIterator(&buffer), | 762 return InternalStringToInt(character_classes, |
| 763 StringInputBufferIterator(&buffer), |
| 728 StringInputBufferIterator::EndMarker(), | 764 StringInputBufferIterator::EndMarker(), |
| 729 radix); | 765 radix); |
| 730 } | 766 } |
| 731 } | 767 } |
| 732 | 768 |
| 733 | 769 |
| 734 double StringToDouble(const char* str, int flags, double empty_string_val) { | 770 double StringToDouble(const char* str, int flags, double empty_string_val) { |
| 771 ScannerCharacterClasses* character_classes = |
| 772 Isolate::Current()->scanner_character_classes(); |
| 735 const char* end = str + StrLength(str); | 773 const char* end = str + StrLength(str); |
| 736 | 774 return InternalStringToDouble(character_classes, str, end, flags, |
| 737 return InternalStringToDouble(str, end, flags, empty_string_val); | 775 empty_string_val); |
| 738 } | 776 } |
| 739 | 777 |
| 740 | 778 |
| 741 extern "C" char* dtoa(double d, int mode, int ndigits, | 779 extern "C" char* dtoa(double d, int mode, int ndigits, |
| 742 int* decpt, int* sign, char** rve); | 780 int* decpt, int* sign, char** rve); |
| 743 | 781 |
| 744 extern "C" void freedtoa(char* s); | 782 extern "C" void freedtoa(char* s); |
| 745 | 783 |
| 746 const char* DoubleToCString(double v, Vector<char> buffer) { | 784 const char* DoubleToCString(double v, Vector<char> buffer) { |
| 747 StringBuilder builder(buffer.start(), buffer.length()); | 785 StringBuilder builder(buffer.start(), buffer.length()); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1110 // Allocate result and fill in the parts. | 1148 // Allocate result and fill in the parts. |
| 1111 StringBuilder builder(result_size + 1); | 1149 StringBuilder builder(result_size + 1); |
| 1112 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); | 1150 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); |
| 1113 if (decimal_pos > 0) builder.AddCharacter('.'); | 1151 if (decimal_pos > 0) builder.AddCharacter('.'); |
| 1114 builder.AddSubstring(decimal_buffer, decimal_pos); | 1152 builder.AddSubstring(decimal_buffer, decimal_pos); |
| 1115 return builder.Finalize(); | 1153 return builder.Finalize(); |
| 1116 } | 1154 } |
| 1117 | 1155 |
| 1118 | 1156 |
| 1119 } } // namespace v8::internal | 1157 } } // namespace v8::internal |
| OLD | NEW |