Commit 93477c22 authored by serya@chromium.org's avatar serya@chromium.org

StringToInt rewritten. This version doesn't allocate memory for long decimals...

StringToInt rewritten. This version doesn't allocate memory for long decimals and uses percise rounding if radix 10 or a power of 2 (in other cases rounding error still may occur). Handling special values moved from Runtime_StringParseInt into StringToInt in order to make it consistent with StringToDouble.


Committed: http://code.google.com/p/v8/source/detail?r=4329
Review URL: http://codereview.chromium.org/1529004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4333 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9738049a
This diff is collapsed.
...@@ -100,8 +100,7 @@ double StringToDouble(const char* str, int flags, double empty_string_val = 0); ...@@ -100,8 +100,7 @@ double StringToDouble(const char* str, int flags, double empty_string_val = 0);
double StringToDouble(String* str, int flags, double empty_string_val = 0); double StringToDouble(String* str, int flags, double empty_string_val = 0);
// Converts a string into an integer. // Converts a string into an integer.
int StringToInt(String* str, int index, int radix, double* value); double StringToInt(String* str, int radix);
int StringToInt(const char* str, int index, int radix, double* value);
// Converts a double to a string value according to ECMA-262 9.8.1. // Converts a double to a string value according to ECMA-262 9.8.1.
// The buffer should be large enough for any floating point number. // The buffer should be large enough for any floating point number.
......
...@@ -4739,49 +4739,9 @@ static Object* Runtime_StringParseInt(Arguments args) { ...@@ -4739,49 +4739,9 @@ static Object* Runtime_StringParseInt(Arguments args) {
s->TryFlatten(); s->TryFlatten();
int len = s->length(); RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
int i; double value = StringToInt(s, radix);
return Heap::NumberFromDouble(value);
// Skip leading white space.
for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
if (i == len) return Heap::nan_value();
// Compute the sign (default to +).
int sign = 1;
if (s->Get(i) == '-') {
sign = -1;
i++;
} else if (s->Get(i) == '+') {
i++;
}
// Compute the radix if 0.
if (radix == 0) {
radix = 10;
if (i < len && s->Get(i) == '0') {
radix = 8;
if (i + 1 < len) {
int c = s->Get(i + 1);
if (c == 'x' || c == 'X') {
radix = 16;
i += 2;
}
}
}
} else if (radix == 16) {
// Allow 0x or 0X prefix if radix is 16.
if (i + 1 < len && s->Get(i) == '0') {
int c = s->Get(i + 1);
if (c == 'x' || c == 'X') i += 2;
}
}
RUNTIME_ASSERT(2 <= radix && radix <= 36);
double value;
int end_index = StringToInt(s, i, radix, &value);
if (end_index != i) {
return Heap::NumberFromDouble(sign * value);
}
return Heap::nan_value(); return Heap::nan_value();
} }
......
...@@ -42,7 +42,10 @@ assertEquals(0x12, parseInt('0x12')); ...@@ -42,7 +42,10 @@ assertEquals(0x12, parseInt('0x12'));
assertEquals(0x12, parseInt('0x12', 16)); assertEquals(0x12, parseInt('0x12', 16));
assertEquals(0x12, parseInt('0x12', 16.1)); assertEquals(0x12, parseInt('0x12', 16.1));
assertEquals(0x12, parseInt('0x12', NaN)); assertEquals(0x12, parseInt('0x12', NaN));
assertTrue(isNaN(parseInt('0x ')));
assertTrue(isNaN(parseInt('0x')));
assertTrue(isNaN(parseInt('0x ', 16)));
assertTrue(isNaN(parseInt('0x', 16)));
assertEquals(12, parseInt('12aaa')); assertEquals(12, parseInt('12aaa'));
assertEquals(0.1, parseFloat('0.1')); assertEquals(0.1, parseFloat('0.1'));
...@@ -51,6 +54,20 @@ assertEquals(0, parseFloat('0aaa')); ...@@ -51,6 +54,20 @@ assertEquals(0, parseFloat('0aaa'));
assertEquals(0, parseFloat('0x12')); assertEquals(0, parseFloat('0x12'));
assertEquals(77, parseFloat('077')); assertEquals(77, parseFloat('077'));
assertEquals(Infinity, parseInt('1000000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '0000000000000'));
assertEquals(Infinity, parseInt('0x10000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000000000000000000000000000000000000000000000000000000000'
+ '0000000000000'));
var i; var i;
var y = 10; var y = 10;
......
...@@ -62,6 +62,10 @@ assertEquals(123, toNumber("\r123\r")); ...@@ -62,6 +62,10 @@ assertEquals(123, toNumber("\r123\r"));
assertEquals(123, toNumber("\t123\t")); assertEquals(123, toNumber("\t123\t"));
assertEquals(123, toNumber("\f123\f")); assertEquals(123, toNumber("\f123\f"));
assertEquals(16, toNumber(" 0x10 "));
assertEquals(NaN, toNumber("0x"));
assertEquals(NaN, toNumber("0x "));
assertTrue(isNaN(toNumber(" NaN "))); assertTrue(isNaN(toNumber(" NaN ")));
assertEquals(Infinity, toNumber(" Infinity ") ," Infinity"); assertEquals(Infinity, toNumber(" Infinity ") ," Infinity");
assertEquals(-Infinity, toNumber(" -Infinity ")); assertEquals(-Infinity, toNumber(" -Infinity "));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment