mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-12 22:33:36 +00:00
Fix parsing C-like hex floats
This commit is contained in:
@@ -556,19 +556,49 @@ parse_f32 :: proc(s: string, n: ^int = nil) -> (value: f32, ok: bool) {
|
||||
return f32(v), ok
|
||||
}
|
||||
|
||||
|
||||
parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
|
||||
value, n^, ok = parse_f64_prefix(str)
|
||||
if ok && len(str) != n^ {
|
||||
ok = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Parses a 32-bit floating point number from a string.
|
||||
//
|
||||
// Returns ok=false if a base 10 float could not be found,
|
||||
// or if the input string contained more than just the number.
|
||||
//
|
||||
// ```
|
||||
// n, _, ok := strconv.parse_f32("12.34eee");
|
||||
// assert(n == 12.34 && ok);
|
||||
//
|
||||
// n, _, ok = strconv.parse_f32("12.34");
|
||||
// assert(n == 12.34 && ok);
|
||||
// ```
|
||||
parse_f32_prefix :: proc(str: string) -> (value: f32, nr: int, ok: bool) {
|
||||
f: f64
|
||||
f, nr, ok = parse_f64_prefix(str)
|
||||
value = f32(f)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Parses a 64-bit floating point number from a string.
|
||||
//
|
||||
// Returns ok=false if a base 10 float could not be found,
|
||||
// or if the input string contained more than just the number.
|
||||
//
|
||||
// ```
|
||||
// n, ok := strconv.parse_f32("12.34eee");
|
||||
// n, _, ok := strconv.parse_f32("12.34eee");
|
||||
// assert(n == 12.34 && ok);
|
||||
//
|
||||
// n, ok = strconv.parse_f32("12.34");
|
||||
// n, _, ok = strconv.parse_f32("12.34");
|
||||
// assert(n == 12.34 && ok);
|
||||
// ```
|
||||
parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
|
||||
parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) {
|
||||
common_prefix_len_ignore_case :: proc "contextless" (s, prefix: string) -> int {
|
||||
n := len(prefix)
|
||||
if n > len(s) {
|
||||
@@ -751,7 +781,7 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
|
||||
mantissa |= 1
|
||||
}
|
||||
|
||||
for mantissa >> (info.mantbits+2) == 0 {
|
||||
for mantissa != 0 && mantissa >> (info.mantbits+2) == 0 {
|
||||
mantissa = mantissa>>1 | mantissa&1
|
||||
exp += 1
|
||||
}
|
||||
@@ -795,9 +825,6 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
|
||||
}
|
||||
|
||||
|
||||
nr: int
|
||||
defer if n != nil { n^ = nr }
|
||||
|
||||
if value, nr, ok = check_special(str); ok {
|
||||
return
|
||||
}
|
||||
@@ -808,7 +835,8 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
|
||||
mantissa, exp, neg, trunc, hex, nr = parse_components(str) or_return
|
||||
|
||||
if hex {
|
||||
return parse_hex(str, mantissa, exp, neg, trunc)
|
||||
value, ok = parse_hex(str, mantissa, exp, neg, trunc)
|
||||
return
|
||||
}
|
||||
|
||||
trunc_block: if !trunc {
|
||||
@@ -827,7 +855,7 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
|
||||
}
|
||||
switch {
|
||||
case exp == 0:
|
||||
return f, true
|
||||
return f, nr, true
|
||||
case exp > 0 && exp <= 15+22:
|
||||
if exp > 22 {
|
||||
f *= pow10[exp-22]
|
||||
@@ -836,9 +864,9 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
|
||||
if f > 1e15 || f < 1e-15 {
|
||||
break trunc_block
|
||||
}
|
||||
return f * pow10[exp], true
|
||||
return f * pow10[exp], nr, true
|
||||
case -22 <= exp && exp < 0:
|
||||
return f / pow10[-exp], true
|
||||
return f / pow10[-exp], nr, true
|
||||
}
|
||||
}
|
||||
d: decimal.Decimal
|
||||
|
||||
Reference in New Issue
Block a user