Browse Source

Add `parse_complex/quaternion*` to `core:strconv`

Feoramund 1 year ago
parent
commit
265e6aa781
1 changed files with 269 additions and 0 deletions
  1. 269 0
      core/strconv/strconv.odin

+ 269 - 0
core/strconv/strconv.odin

@@ -1124,6 +1124,275 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) {
 	ok = !overflow
 	ok = !overflow
 	return
 	return
 }
 }
+/*
+Parses a 128-bit complex number from a string
+
+**Inputs**  
+- str: The input string containing a 128-bit complex number.
+- n: An optional pointer to an int to store the length of the parsed substring (default: nil).
+
+Example:
+
+	import "core:fmt"
+	import "core:strconv"
+	parse_complex128_example :: proc() {
+		n: int
+		c, ok := strconv.parse_complex128("3+1i", &n)
+		fmt.printfln("%v %i %t", c, n, ok)
+
+		c, ok = strconv.parse_complex128("5+7i hellope", &n)
+		fmt.printfln("%v %i %t", c, n, ok)
+	}
+	
+Output:
+
+	3+1i 4 true
+	5+7i 4 false
+	
+**Returns**  
+- value: The parsed 128-bit complex number.
+- ok: `false` if a complex number could not be found, or if the input string contained more than just the number.
+*/
+parse_complex128 :: proc(str: string, n: ^int = nil) -> (value: complex128, ok: bool) {
+	real_value, imag_value: f64
+	nr_r, nr_i: int
+
+	real_value, nr_r, _ = parse_f64_prefix(str)
+	imag_value, nr_i, _ = parse_f64_prefix(str[nr_r:])
+
+	i_parsed := len(str) >= nr_r + nr_i + 1 && str[nr_r + nr_i] == 'i'
+	if !i_parsed {
+		// No `i` means we refuse to treat the second float we parsed as an
+		// imaginary value.
+		imag_value = 0
+		nr_i = 0
+	}
+
+	ok = i_parsed && len(str) == nr_r + nr_i + 1
+
+	if n != nil {
+		n^ = nr_r + nr_i + (1 if i_parsed else 0)
+	}
+
+	value = complex(real_value, imag_value)
+	return 
+}
+/*
+Parses a 64-bit complex number from a string
+
+**Inputs**  
+- str: The input string containing a 64-bit complex number.
+- n: An optional pointer to an int to store the length of the parsed substring (default: nil).
+
+Example:
+
+	import "core:fmt"
+	import "core:strconv"
+	parse_complex64_example :: proc() {
+		n: int
+		c, ok := strconv.parse_complex64("3+1i", &n)
+		fmt.printfln("%v %i %t", c, n, ok)
+
+		c, ok = strconv.parse_complex64("5+7i hellope", &n)
+		fmt.printfln("%v %i %t", c, n, ok)
+	}
+	
+Output:
+
+	3+1i 4 true
+	5+7i 4 false
+	
+**Returns**  
+- value: The parsed 64-bit complex number.
+- ok: `false` if a complex number could not be found, or if the input string contained more than just the number.
+*/
+parse_complex64 :: proc(str: string, n: ^int = nil) -> (value: complex64, ok: bool) {
+	v: complex128 = ---
+	v, ok = parse_complex128(str, n)
+	return cast(complex64)v, ok
+}
+/*
+Parses a 32-bit complex number from a string
+
+**Inputs**  
+- str: The input string containing a 32-bit complex number.
+- n: An optional pointer to an int to store the length of the parsed substring (default: nil).
+
+Example:
+
+	import "core:fmt"
+	import "core:strconv"
+	parse_complex32_example :: proc() {
+		n: int
+		c, ok := strconv.parse_complex32("3+1i", &n)
+		fmt.printfln("%v %i %t", c, n, ok)
+
+		c, ok = strconv.parse_complex32("5+7i hellope", &n)
+		fmt.printfln("%v %i %t", c, n, ok)
+	}
+	
+Output:
+
+	3+1i 4 true
+	5+7i 4 false
+	
+**Returns**  
+- value: The parsed 32-bit complex number.
+- ok: `false` if a complex number could not be found, or if the input string contained more than just the number.
+*/
+parse_complex32 :: proc(str: string, n: ^int = nil) -> (value: complex32, ok: bool) {
+	v: complex128 = ---
+	v, ok = parse_complex128(str, n)
+	return cast(complex32)v, ok
+}
+/*
+Parses a 256-bit quaternion from a string
+
+**Inputs**  
+- str: The input string containing a 256-bit quaternion.
+- n: An optional pointer to an int to store the length of the parsed substring (default: nil).
+
+Example:
+
+	import "core:fmt"
+	import "core:strconv"
+	parse_quaternion256_example :: proc() {
+		n: int
+		q, ok := strconv.parse_quaternion256("1+2i+3j+4k", &n)
+		fmt.printfln("%v %i %t", q, n, ok)
+
+		q, ok = strconv.parse_quaternion256("1+2i+3j+4k hellope", &n)
+		fmt.printfln("%v %i %t", q, n, ok)
+	}
+	
+Output:
+
+	1+2i+3j+4k 10 true
+	1+2i+3j+4k 10 false
+	
+**Returns**  
+- value: The parsed 256-bit quaternion.
+- ok: `false` if a quaternion could not be found, or if the input string contained more than just the quaternion.
+*/
+parse_quaternion256 :: proc(str: string, n: ^int = nil) -> (value: quaternion256, ok: bool) {
+	iterate_and_assign :: proc (iter: ^string, terminator: byte, nr_total: ^int, state: bool) -> (value: f64, ok: bool) {
+		if !state {
+			return
+		}
+
+		nr: int
+		value, nr, _ = parse_f64_prefix(iter^)
+		iter^ = iter[nr:]
+
+		if len(iter) > 0 && iter[0] == terminator {
+			iter^ = iter[1:]
+			nr_total^ += nr + 1
+			ok = true
+		} else {
+			value = 0
+		}
+
+		return
+	}
+
+	real_value, imag_value, jmag_value, kmag_value: f64
+	nr: int
+
+	real_value, nr, _ = parse_f64_prefix(str)
+	iter := str[nr:]
+
+	// Need to have parsed at least something in order to get started.
+	ok = nr > 0
+
+	// Quaternion parsing is done this way to honour the rest of the API with
+	// regards to partial parsing. Otherwise, we could error out early.
+	imag_value, ok = iterate_and_assign(&iter, 'i', &nr, ok)
+	jmag_value, ok = iterate_and_assign(&iter, 'j', &nr, ok)
+	kmag_value, ok = iterate_and_assign(&iter, 'k', &nr, ok)
+
+	if len(iter) != 0 {
+		ok = false
+	}
+
+	if n != nil {
+		n^ = nr
+	}
+
+	value = quaternion(
+		real = real_value,
+		imag = imag_value,
+		jmag = jmag_value,
+		kmag = kmag_value)
+	return
+}
+/*
+Parses a 128-bit quaternion from a string
+
+**Inputs**  
+- str: The input string containing a 128-bit quaternion.
+- n: An optional pointer to an int to store the length of the parsed substring (default: nil).
+
+Example:
+
+	import "core:fmt"
+	import "core:strconv"
+	parse_quaternion128_example :: proc() {
+		n: int
+		q, ok := strconv.parse_quaternion128("1+2i+3j+4k", &n)
+		fmt.printfln("%v %i %t", q, n, ok)
+
+		q, ok = strconv.parse_quaternion128("1+2i+3j+4k hellope", &n)
+		fmt.printfln("%v %i %t", q, n, ok)
+	}
+	
+Output:
+
+	1+2i+3j+4k 10 true
+	1+2i+3j+4k 10 false
+	
+**Returns**  
+- value: The parsed 128-bit quaternion.
+- ok: `false` if a quaternion could not be found, or if the input string contained more than just the quaternion.
+*/
+parse_quaternion128 :: proc(str: string, n: ^int = nil) -> (value: quaternion128, ok: bool) {
+	v: quaternion256 = ---
+	v, ok = parse_quaternion256(str, n)
+	return cast(quaternion128)v, ok
+}
+/*
+Parses a 64-bit quaternion from a string
+
+**Inputs**  
+- str: The input string containing a 64-bit quaternion.
+- n: An optional pointer to an int to store the length of the parsed substring (default: nil).
+
+Example:
+
+	import "core:fmt"
+	import "core:strconv"
+	parse_quaternion64_example :: proc() {
+		n: int
+		q, ok := strconv.parse_quaternion64("1+2i+3j+4k", &n)
+		fmt.printfln("%v %i %t", q, n, ok)
+
+		q, ok = strconv.parse_quaternion64("1+2i+3j+4k hellope", &n)
+		fmt.printfln("%v %i %t", q, n, ok)
+	}
+	
+Output:
+
+	1+2i+3j+4k 10 true
+	1+2i+3j+4k 10 false
+	
+**Returns**  
+- value: The parsed 64-bit quaternion.
+- ok: `false` if a quaternion could not be found, or if the input string contained more than just the quaternion.
+*/
+parse_quaternion64 :: proc(str: string, n: ^int = nil) -> (value: quaternion64, ok: bool) {
+	v: quaternion256 = ---
+	v, ok = parse_quaternion256(str, n)
+	return cast(quaternion64)v, ok
+}
 /* 
 /* 
 Appends a boolean value as a string to the given buffer
 Appends a boolean value as a string to the given buffer