Chromium Code Reviews| Index: runtime/lib/double_patch.dart |
| diff --git a/runtime/lib/double_patch.dart b/runtime/lib/double_patch.dart |
| index d8e0cbd0c8450825ce4460e4af4e0a60d7291337..80916d3e569934c954deaf197878a3494e85912c 100644 |
| --- a/runtime/lib/double_patch.dart |
| +++ b/runtime/lib/double_patch.dart |
| @@ -10,13 +10,109 @@ patch class double { |
| static double _nativeParse(String str, |
| int start, int end) native "Double_parse"; |
| + static double _tryParseShortDouble(var str, var start, var end) { |
| + assert(start < end); |
| + const int _DOT = 0x2e; // '.' |
| + const int _ZERO = 0x30; // '0' |
| + const int _MINUS = 0x2d; // '-' |
| + const int _N = 0x4e; // 'N' |
| + const int _a = 0x61; // 'a' |
| + const int _I = 0x49; // 'I' |
| + const int _e = 0x65; // 'e' |
| + int exponent = 0; |
| + // Added to exponent for each digit. Set to -1 when seeing '.'. |
| + int exponentDelta = 0; |
| + double doubleValue = 0.0; |
| + double sign = 1.0; |
| + int i = start; |
| + int c = str.codeUnitAt(i); |
| + if (c == _MINUS) { |
| + sign = -1.0; |
| + i = start = start + 1; // Use 'start' as start of digits. |
| + if (i == end) return null; |
| + c = str.codeUnitAt(i); |
| + } |
| + if (c == _I) { |
| + if (end == start + 8 && str.startsWith("nfinity", i + 1)) { |
| + return sign * double.INFINITY; |
| + } |
| + return null; |
| + } |
| + if (c == _N) { |
| + if (end == start + 3 && str.codeUnitAt(i + 1) == _a |
| + && str.codeUnitAt(i + 2) == _N) { |
| + return double.NAN; |
| + } |
| + return null; |
| + } |
| + while (true) { |
| + int digit = c ^ _ZERO; // '0'-'9' characters are now 0-9 integers. |
| + if (digit <= 9) { |
| + doubleValue = doubleValue * 10 + digit; |
| + if (doubleValue >= 9007199254740992.0) return null; // Maybe unprecise. |
| + exponent += exponentDelta; |
| + } else if (c == _DOT && exponentDelta == 0) { |
| + exponentDelta = -1; |
| + } else if (c | 0x20 == _e) { |
| + if (i + 1 == end) return null; |
| + int expPart = int._tryParseSmi(str, i + 1, end - 1); |
| + if (expPart == null) return null; |
| + exponent += expPart; |
| + break; |
| + } else { |
| + return null; |
| + } |
| + i++; |
| + if (i == end) break; |
| + c = str.codeUnitAt(i); |
| + } |
| + if (i - start + exponentDelta == 0) return null; // No digits. |
| + if (exponent == 0) return sign * doubleValue; |
| + // Powers of 10 up to 10^22 are exact doubles. |
| + const P10 = const [ |
| + 1.0, /* 0 */ |
| + 10.0, |
| + 100.0, |
| + 1000.0, |
| + 10000.0, |
| + 100000.0, /* 5 */ |
| + 1000000.0, |
| + 10000000.0, |
| + 100000000.0, |
| + 1000000000.0, |
| + 10000000000.0, /* 10 */ |
| + 100000000000.0, |
| + 1000000000000.0, |
| + 10000000000000.0, |
| + 100000000000000.0, |
| + 1000000000000000.0, /* 15 */ |
| + 10000000000000000.0, |
| + 100000000000000000.0, |
| + 1000000000000000000.0, |
| + 10000000000000000000.0, |
| + 100000000000000000000.0, /* 20 */ |
| + 1000000000000000000000.0, |
| + 10000000000000000000000.0, |
| + ]; |
| + if (exponent < 0) { |
| + if (exponent < -22) return null; |
| + return sign * (doubleValue / P10[-exponent]); |
| + } |
| + if (exponent > 22) return null; |
| + return sign * (doubleValue * P10[exponent]); |
| + } |
| + |
| static double _parse(var str) { |
| int len = str.length; |
| int start = str._firstNonWhitespace(); |
| if (start == len) return null; // All whitespace. |
| int end = str._lastNonWhitespace() + 1; |
| assert(start < end); |
| - |
| + int length = end - start; |
| + if (length < 16) { |
|
floitsch
2014/09/29 14:51:34
Given that exponents don't count in the limit, you
Lasse Reichstein Nielsen
2014/09/30 05:45:30
Ack, I forgot the limit was even there. I have a v
|
| + var result = _tryParseShortDouble(str, start, end); |
| + if (result != null) return result; |
| + } |
| return _nativeParse(str, start, end); |
| } |