Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: spec compliant parseInt #1378

Merged
merged 17 commits into from
Jul 9, 2020
Merged
4 changes: 2 additions & 2 deletions std/assembly/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export abstract class F32 {
}

static parseInt(value: string, radix: i32 = 0): f32 {
return <f32>strtol<i64>(value, radix);
return <f32>strtol<f64>(value, radix);
dcodeIO marked this conversation as resolved.
Show resolved Hide resolved
}

static parseFloat(value: string): f32 {
Expand Down Expand Up @@ -359,7 +359,7 @@ export abstract class F64 {
}

static parseInt(value: string, radix: i32 = 0): f64 {
return <f64>strtol<i64>(value, radix);
return strtol<f64>(value, radix);
}

static parseFloat(value: string): f64 {
Expand Down
69 changes: 47 additions & 22 deletions std/assembly/util/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,39 +652,48 @@ export function toUpper8(c: u32): u32 {
export function strtol<T>(str: string, radix: i32 = 0): T {
var len = str.length;
if (!len) {
// @ts-ignore: cast
if (isFloat<T>()) return <T>NaN;
// @ts-ignore: cast
return <T>0;
if (isFloat<T>()) {
// @ts-ignore: cast
return <T>NaN;
} else {
// @ts-ignore: cast
return <T>0;
}
}

var ptr = changetype<usize>(str) /* + HEAD -> offset */;
var code = <u32>load<u16>(ptr);

// determine sign
// @ts-ignore: cast
var sign: T = 1;
var sign = false;
MaxGraey marked this conversation as resolved.
Show resolved Hide resolved
// trim white spaces
while (isSpace(code)) {
code = <u32>load<u16>(ptr += 2);
--len;
}
if (code == CharCode.MINUS) {
if (!--len) {
// @ts-ignore: cast
if (isFloat<T>()) return <T>NaN;
// @ts-ignore: cast
return <T>0;
if (isFloat<T>()) {
// @ts-ignore: cast
return <T>NaN;
} else {
// @ts-ignore: cast
return <T>0;
}
}
code = <u32>load<u16>(ptr += 2);
// @ts-ignore: type
sign = -1;
sign = true;
} else if (code == CharCode.PLUS) {
if (!--len) {
// @ts-ignore: cast
if (isFloat<T>()) return <T>NaN;
// @ts-ignore: cast
return <T>0;
if (isFloat<T>()) {
// @ts-ignore: cast
return <T>NaN;
} else {
// @ts-ignore: cast
return <T>0;
}
}
code = <u32>load<u16>(ptr += 2);
}
Expand Down Expand Up @@ -712,15 +721,18 @@ export function strtol<T>(str: string, radix: i32 = 0): T {
}
} else radix = 10;
} else if (radix < 2 || radix > 36) {
// @ts-ignore: cast
if (isFloat<T>()) return <T>NaN;
// @ts-ignore: cast
return <T>0;
if (isFloat<T>()) {
// @ts-ignore: cast
return <T>NaN;
} else {
// @ts-ignore: cast
return <T>0;
}
}

// calculate value
// @ts-ignore: type
var num: T = 0;
var num: i64 = 0;
while (len--) {
code = <u32>load<u16>(ptr);
if (code - CharCode._0 < 10) {
Expand All @@ -729,14 +741,27 @@ export function strtol<T>(str: string, radix: i32 = 0): T {
code -= CharCode.A - 10;
} else if (code - CharCode.a <= <u32>(CharCode.z - CharCode.a)) {
code -= CharCode.a - 10;
} else break;
if (code >= <u32>radix) break;
}
if (code >= <u32>radix) {
if (!num) {
if (isFloat<T>()) {
// @ts-ignore: cast
return <T>NaN;
} else {
// @ts-ignore: cast
return <T>0;
}
}
break;
}
// @ts-ignore: type
num = num * radix + code;
ptr += 2;
}
// @ts-ignore: cast
var res = <T>num;
// @ts-ignore: type
return sign * num;
return sign ? -res : res;
}

export function strtod(str: string): f64 {
Expand Down
Loading