فهرست منبع

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.
Feoramund 1 سال پیش
والد
کامیت
25feff3eb4
2فایلهای تغییر یافته به همراه26 افزوده شده و 29 حذف شده
  1. 8 2
      core/strconv/strconv.odin
  2. 18 27
      tests/core/strconv/test_core_strconv.odin

+ 8 - 2
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
 				}

+ 18 - 27
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"
-			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"
+		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, 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"
-			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"
+		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, 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)