Implement strtof

This commit is contained in:
jD91mZM2
2018-09-29 20:51:38 +02:00
parent aec6a48ca4
commit 6dcc8ee8d9
2 changed files with 68 additions and 55 deletions
+6 -55
View File
@@ -675,61 +675,12 @@ pub extern "C" fn srandom(seed: c_uint) {
}
#[no_mangle]
pub unsafe extern "C" fn strtod(mut s: *const c_char, endptr: *mut *mut c_char) -> c_double {
while ctype::isspace(*s as c_int) != 0 {
s = s.offset(1);
}
let mut result = 0.0;
let mut radix = 10;
let negative = match *s as u8 {
b'-' => {
s = s.offset(1);
true
}
b'+' => {
s = s.offset(1);
false
}
_ => false,
};
if *s as u8 == b'0' && *s.offset(1) as u8 == b'x' {
s = s.offset(2);
radix = 16;
}
while let Some(digit) = (*s as u8 as char).to_digit(radix) {
result *= radix as c_double;
result += digit as c_double;
s = s.offset(1);
}
if *s as u8 == b'.' {
s = s.offset(1);
let mut i = 1.0;
while let Some(digit) = (*s as u8 as char).to_digit(radix) {
i *= radix as c_double;
result += digit as c_double / i;
s = s.offset(1);
}
}
if !endptr.is_null() {
// This is stupid, but apparently strto* functions want
// const input but mut output, yet the man page says
// "stores the address of the first invalid character in *endptr"
// so obviously it doesn't want us to clone it.
*endptr = s as *mut _;
}
if negative {
-result
} else {
result
}
pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
strto_float_impl!(c_double, s, endptr)
}
#[no_mangle]
pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> c_float {
strto_float_impl!(c_float, s, endptr)
}
pub fn is_positive(ch: c_char) -> Option<(bool, isize)> {
+62
View File
@@ -190,3 +190,65 @@ macro_rules! strto_impl {
num
}};
}
#[macro_export]
macro_rules! strto_float_impl {
($type:ident, $s:expr, $endptr:expr) => {{
let mut s = $s;
let endptr = $endptr;
while ctype::isspace(*s as c_int) != 0 {
s = s.offset(1);
}
let mut result: $type = 0.0;
let mut radix = 10;
let negative = match *s as u8 {
b'-' => {
s = s.offset(1);
true
}
b'+' => {
s = s.offset(1);
false
}
_ => false,
};
if *s as u8 == b'0' && *s.offset(1) as u8 == b'x' {
s = s.offset(2);
radix = 16;
}
while let Some(digit) = (*s as u8 as char).to_digit(radix) {
result *= radix as $type;
result += digit as $type;
s = s.offset(1);
}
if *s as u8 == b'.' {
s = s.offset(1);
let mut i = 1.0;
while let Some(digit) = (*s as u8 as char).to_digit(radix) {
i *= radix as $type;
result += digit as $type / i;
s = s.offset(1);
}
}
if !endptr.is_null() {
// This is stupid, but apparently strto* functions want
// const input but mut output, yet the man page says
// "stores the address of the first invalid character in *endptr"
// so obviously it doesn't want us to clone it.
*endptr = s as *mut _;
}
if negative {
-result
} else {
result
}
}}
}