From 25feff3eb4c3845e6da4e8e56010301e316b2dd9 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Tue, 4 Jun 2024 18:50:08 -0400 Subject: [PATCH] Permit parsing of incomplete `infinity` but do not return true To clarify, `parse_f64` will indeed take `infi` to mean `+Inf` and return that as the value, but it will not return `ok = true`. It treats it as `inf` followed by any other trailing character. `parse_f64_prefix` is the lenient one which will return true so long as it finds some meaningful value. --- core/strconv/strconv.odin | 10 ++++- tests/core/strconv/test_core_strconv.odin | 45 +++++++++-------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index 990b2be2f..60b4b4e2e 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -879,9 +879,15 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { fallthrough case 'i', 'I': m := common_prefix_len_ignore_case(s, "infinity") - if m == 3 || m == 8 { // "inf" or "infinity" + if 3 <= m && m < 9 { // "inf" to "infinity" f = 0h7ff00000_00000000 if sign == 1 else 0hfff00000_00000000 - n = nsign + m + if m == 8 { + // We only count the entire prefix if it is precisely "infinity". + n = nsign + m + } else { + // The string was either only "inf" or incomplete. + n = nsign + 3 + } ok = true return } diff --git a/tests/core/strconv/test_core_strconv.odin b/tests/core/strconv/test_core_strconv.odin index ed4adaf01..6b70654cc 100644 --- a/tests/core/strconv/test_core_strconv.odin +++ b/tests/core/strconv/test_core_strconv.odin @@ -62,18 +62,15 @@ test_infinity :: proc(t: ^testing.T) { n: int s := "infinity" - for i in 1 ..< len(s) + 1 { + for i in 0 ..< len(s) + 1 { ss := s[:i] f, ok := strconv.parse_f64(ss, &n) - if i == 3 { // "inf" + if i >= 3 { // "inf" .. "infinity" + expected_n := 8 if i == 8 else 3 + expected_ok := i == 3 || i == 8 testing.expect_value(t, f, pos_inf) - testing.expect_value(t, n, 3) - testing.expect_value(t, ok, true) - testing.expect_value(t, math.classify(f), math.Float_Class.Inf) - } else if i == 8 { // "infinity" - testing.expect_value(t, f, pos_inf) - testing.expect_value(t, n, 8) - testing.expect_value(t, ok, true) + testing.expect_value(t, n, expected_n) + testing.expect_value(t, ok, expected_ok) testing.expect_value(t, math.classify(f), math.Float_Class.Inf) } else { // invalid substring testing.expect_value(t, f, 0) @@ -84,18 +81,15 @@ test_infinity :: proc(t: ^testing.T) { } s = "+infinity" - for i in 1 ..< len(s) + 1 { + for i in 0 ..< len(s) + 1 { ss := s[:i] f, ok := strconv.parse_f64(ss, &n) - if i == 4 { // "+inf" + if i >= 4 { // "+inf" .. "+infinity" + expected_n := 9 if i == 9 else 4 + expected_ok := i == 4 || i == 9 testing.expect_value(t, f, pos_inf) - testing.expect_value(t, n, 4) - testing.expect_value(t, ok, true) - testing.expect_value(t, math.classify(f), math.Float_Class.Inf) - } else if i == 9 { // "+infinity" - testing.expect_value(t, f, pos_inf) - testing.expect_value(t, n, 9) - testing.expect_value(t, ok, true) + testing.expect_value(t, n, expected_n) + testing.expect_value(t, ok, expected_ok) testing.expect_value(t, math.classify(f), math.Float_Class.Inf) } else { // invalid substring testing.expect_value(t, f, 0) @@ -106,18 +100,15 @@ test_infinity :: proc(t: ^testing.T) { } s = "-infinity" - for i in 1 ..< len(s) + 1 { + for i in 0 ..< len(s) + 1 { ss := s[:i] f, ok := strconv.parse_f64(ss, &n) - if i == 4 { // "-inf" + if i >= 4 { // "-inf" .. "infinity" + expected_n := 9 if i == 9 else 4 + expected_ok := i == 4 || i == 9 testing.expect_value(t, f, neg_inf) - testing.expect_value(t, n, 4) - testing.expect_value(t, ok, true) - testing.expect_value(t, math.classify(f), math.Float_Class.Neg_Inf) - } else if i == 9 { // "-infinity" - testing.expect_value(t, f, neg_inf) - testing.expect_value(t, n, 9) - testing.expect_value(t, ok, true) + testing.expect_value(t, n, expected_n) + testing.expect_value(t, ok, expected_ok) testing.expect_value(t, math.classify(f), math.Float_Class.Neg_Inf) } else { // invalid substring testing.expect_value(t, f, 0)