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