diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2022-09-28 16:41:26 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2022-09-28 16:41:26 +0200 |
| commit | cd910b1512a3f3815417327af15c2eae0e763154 (patch) | |
| tree | 2ad21569c1ca10afbd1ff22b7fdfd3173679864a /core/strconv | |
| parent | efa86ddf467bd249ca2f897de1e88bacf758014d (diff) | |
[strconv] Add parsing of Inf & NaN
Diffstat (limited to 'core/strconv')
| -rw-r--r-- | core/strconv/strconv.odin | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index c2d48be7a..ae89722bf 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -567,7 +567,7 @@ parse_f32 :: proc(s: string, n: ^int = nil) -> (value: f32, ok: bool) { // ``` parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { s := str - defer if n != nil { n^ = len(str)-len(s) } + defer if n != nil { n^ = len(str) - len(s) } if s == "" { return } @@ -588,6 +588,38 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { v := _digit_value(r) if v >= 10 { + if r == '.' || r == 'e' || r == 'E' { // Skip parsing NaN and Inf if it's probably a regular float + break + } + if len(s) >= 3 + i { + buf: [4]u8 + copy(buf[:], s[i:][:3]) + + v2 := transmute(u32)buf + v2 &= 0xDFDFDFDF // Knock out lower-case bits + + buf = transmute([4]u8)v2 + + when ODIN_ENDIAN == .Little { + if v2 == 0x464e49 { // "INF" + s = s[3+i:] + value = 0h7ff00000_00000000 if sign == 1 else 0hfff00000_00000000 + return value, len(s) == 0 + } else if v2 == 0x4e414e { // "NAN" + s = s[3+i:] + return 0h7ff80000_00000001, len(s) == 0 + } + } else { + if v2 == 0x494e4600 { // "\0FNI" + s = s[3+i:] + value = 0h7ff00000_00000000 if sign == 1 else 0hfff00000_00000000 + return value, len(s) == 0 + } else if v2 == 0x4e414e00 { // "\0NAN" + s = s[3+i:] + return 0h7ff80000_00000001, len(s) == 0 + } + } + } break } value *= 10 |