aboutsummaryrefslogtreecommitdiff
path: root/core/strconv
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2022-09-28 16:41:26 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2022-09-28 16:41:26 +0200
commitcd910b1512a3f3815417327af15c2eae0e763154 (patch)
tree2ad21569c1ca10afbd1ff22b7fdfd3173679864a /core/strconv
parentefa86ddf467bd249ca2f897de1e88bacf758014d (diff)
[strconv] Add parsing of Inf & NaN
Diffstat (limited to 'core/strconv')
-rw-r--r--core/strconv/strconv.odin34
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