[librsvg/rustification] strtod.rs: Shitty implementation of strtod(); we'll need it to parse things easily



commit fb723fade7b904c77f7af71ee2ccc3ae35d522d6
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Nov 9 22:58:08 2016 -0600

    strtod.rs: Shitty implementation of strtod(); we'll need it to parse things easily

 rust/src/lib.rs    |    1 +
 rust/src/strtod.rs |  172 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 173 insertions(+), 0 deletions(-)
---
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index e9adc6d..76e2e77 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -20,3 +20,4 @@ pub use path_parser::{
 mod path_builder;
 mod path_parser;
 mod marker;
+mod strtod;
diff --git a/rust/src/strtod.rs b/rust/src/strtod.rs
new file mode 100644
index 0000000..bba2636
--- /dev/null
+++ b/rust/src/strtod.rs
@@ -0,0 +1,172 @@
+enum State {
+    Whitespace,
+    IntegralPart,
+    FractionalPart,
+    ExponentSign,
+    Exponent
+}
+
+pub fn strtod (string: &str) -> (f64, &str) {
+    let mut state = State::Whitespace;
+    let mut value: f64 = 0.0;
+    let mut sign: f64 = 1.0;
+    let mut fraction: f64 = 1.0;
+    let mut exponent_sign: f64 = 1.0;
+    let mut exponent: f64 = 0.0;
+    let mut last_pos: usize = 0;
+
+    for (pos, c) in string.chars ().enumerate () {
+        last_pos = pos;
+
+        match state {
+            State::Whitespace => {
+                if c.is_whitespace () {
+                    last_pos += 1;
+                    continue;
+                } else if c == '+' || c == '-' {
+                    if c == '-' {
+                        sign = -1.0;
+                    }
+
+                    last_pos += 1;
+                    state = State::IntegralPart;
+                } else if c.is_digit (10) {
+                    state = State::IntegralPart;
+                    value = (c as i32 - '0' as i32) as f64;
+                    last_pos += 1;
+                    println! ("sign: value={}", value);
+                } else if c == '.' {
+                    last_pos += 1;
+                    state = State::FractionalPart;
+                } else {
+                    break;
+                }
+            },
+
+            State::IntegralPart => {
+                if c.is_digit (10) {
+                    value = value * 10.0 + (c as i32 - '0' as i32) as f64;
+                    last_pos += 1;
+                    println! ("int: value={}", value);
+                } else if c == '.' {
+                    last_pos += 1;
+                    state = State::FractionalPart;
+                } else if c == 'e' || c == 'E' {
+                    last_pos += 1;
+                    state = State::ExponentSign;
+                } else {
+                    break;
+                }
+            },
+
+            State::FractionalPart => {
+                if c.is_digit (10) {
+                    fraction *= 0.1;
+                    value += fraction * (c as i32 - '0' as i32) as f64;
+                    println! ("frac: value={}", value);
+                    last_pos += 1;
+                } else if c == 'e' || c == 'E' {
+                    last_pos += 1;
+                    state = State::ExponentSign;
+                } else {
+                    break;
+                }
+            },
+
+            State::ExponentSign => {
+                if c == '+' || c == '-' {
+                    if c == '-' {
+                        exponent_sign = -1.0;
+                    }
+
+                    last_pos += 1;
+                    state = State::Exponent;
+                } else if c.is_digit (10) {
+                    last_pos += 1;
+                    exponent = (c as i32 - '0' as i32) as f64;
+                } else {
+                    break;
+                }
+            },
+
+            State::Exponent => {
+                if c.is_digit (10) {
+                    last_pos += 1;
+                    exponent = exponent * 10.0 + (c as i32 - '0' as i32) as f64;
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    // return tuple with the value and the non-matching slice
+
+    (sign * value * 10.0f64.powf (exponent * exponent_sign),
+     &string[last_pos .. ])
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn handles_empty_string () {
+        let str = "";
+        assert_eq! (strtod (str), (0.0f64, &str[0..]));
+    }
+
+    #[test]
+    fn handles_integer () {
+        let str = "-123foo";
+        assert_eq! (strtod (str), (-123.0f64, &str[4..]));
+
+        let str = "12345";
+        assert_eq! (strtod (str), (12345.0f64, &str[5..]));
+    }
+
+    #[test]
+    fn handles_float () {
+        let str = "-123.25";
+        assert_eq! (strtod (str), (-123.25f64, &str[7..]));
+
+        let str = "123.25bar";
+        assert_eq! (strtod (str), (123.25f64, &str[6..]));
+    }
+
+    #[test]
+    fn handles_dot_numbers () {
+        let str = "-.25foo";
+        assert_eq! (strtod (str), (-0.25f64, &str[4..]));
+
+        let str = ".25";
+        assert_eq! (strtod (str), (0.25f64, &str[3..]));
+    }
+
+    #[test]
+    fn handles_dot () {
+        let str = "-.";
+        assert_eq! (strtod (str), (-0.0, &str[2..]));
+
+        let str = ".bar";
+        assert_eq! (strtod (str), (0.0, &str[1..]));
+    }
+
+    #[test]
+    fn handles_exponent () {
+        let str = "-123.45e2foo";
+        assert_eq! (strtod (str), (-12345.0, &str[9..]));
+
+        let str = "123.45E2";
+        assert_eq! (strtod (str), (12345.0, &str[8..]));
+    }
+
+    #[test]
+    fn handles_negative_exponent () {
+        let str = "-123.25e-2";
+        assert_eq! (strtod (str), (-1.2325, &str[10..]));
+
+        let str = "123.25E-2bar";
+        assert_eq! (strtod (str), (1.2325, &str[9..]));
+    }
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]