Browse Source

add hexfloat (0h) parsing to strconv

Laytan Laats 3 months ago
parent
commit
ebc63a7355
2 changed files with 70 additions and 0 deletions
  1. 33 0
      core/strconv/strconv.odin
  2. 37 0
      tests/core/strconv/test_core_strconv.odin

+ 33 - 0
core/strconv/strconv.odin

@@ -1095,6 +1095,39 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) {
 		return transmute(f64)bits, ok
 	}
 
+	if len(str) > 2 && str[0] == '0' && str[1] == 'h' {
+		nr = 2
+
+		as_int: u64
+		digits: int
+		for r in str[2:] {
+			if r == '_' {
+				nr += 1
+				continue
+			}
+			v := u64(_digit_value(r))
+			if v >= 16 {
+				break
+			}
+			as_int *= 16
+			as_int += v
+			digits += 1
+		}
+		nr += digits
+		ok = len(str) == nr
+
+		switch digits {
+		case 4:
+			value = cast(f64)transmute(f16)cast(u16)as_int
+		case 8:
+			value = cast(f64)transmute(f32)cast(u32)as_int
+		case 16:
+			value = transmute(f64)as_int
+		case:
+			ok = false
+		}
+		return
+	}
 
 	if value, nr, ok = check_special(str); ok {
 		return

+ 37 - 0
tests/core/strconv/test_core_strconv.odin

@@ -30,6 +30,43 @@ test_float :: proc(t: ^testing.T) {
 	testing.expect_value(t, n, 0)
 	testing.expect_value(t, ok, false)
 
+	f, ok = strconv.parse_f64("0", &n)
+	testing.expect_value(t, f, 0)
+	testing.expect_value(t, n, 1)
+	testing.expect_value(t, ok, true)
+
+	f, ok = strconv.parse_f64("0h", &n)
+	testing.expect_value(t, f, 0)
+	testing.expect_value(t, n, 1)
+	testing.expect_value(t, ok, false)
+
+	f, ok = strconv.parse_f64("0h1", &n)
+	testing.expect_value(t, f, 0)
+	testing.expect_value(t, n, 3)
+	testing.expect_value(t, ok, false)
+
+	f, ok = strconv.parse_f64("0h0000_0001", &n)
+	testing.expect_value(t, f, 0h0000_0001)
+	testing.expect_value(t, n, 11)
+	testing.expect_value(t, ok, true)
+
+	f, ok = strconv.parse_f64("0h4c60", &n)
+	testing.expect_value(t, f, 0h4c60)
+	testing.expect_value(t, f, 17.5)
+	testing.expect_value(t, n, 6)
+	testing.expect_value(t, ok, true)
+
+	f, ok = strconv.parse_f64("0h418c0000", &n)
+	testing.expect_value(t, f, 0h418c0000)
+	testing.expect_value(t, f, 17.5)
+	testing.expect_value(t, n, 10)
+	testing.expect_value(t, ok, true)
+
+	f, ok = strconv.parse_f64("0h4031_8000_0000_0000", &n)
+	testing.expect_value(t, f, 0h4031800000000000)
+	testing.expect_value(t, f, f64(17.5))
+	testing.expect_value(t, n, 21)
+	testing.expect_value(t, ok, true)
 }
 
 @(test)