Merge branch 'fix-float-parser' into 'master'
strtof, strtod: Fix parsing floats with exponents See merge request redox-os/relibc!344
This commit is contained in:
+57
-7
@@ -233,6 +233,8 @@ macro_rules! strto_float_impl {
|
||||
let mut s = $s;
|
||||
let endptr = $endptr;
|
||||
|
||||
// TODO: Handle named floats: NaN, Inf...
|
||||
|
||||
while ctype::isspace(*s as c_int) != 0 {
|
||||
s = s.offset(1);
|
||||
}
|
||||
@@ -240,16 +242,16 @@ macro_rules! strto_float_impl {
|
||||
let mut result: $type = 0.0;
|
||||
let mut radix = 10;
|
||||
|
||||
let negative = match *s as u8 {
|
||||
let result_sign = match *s as u8 {
|
||||
b'-' => {
|
||||
s = s.offset(1);
|
||||
true
|
||||
-1.0
|
||||
}
|
||||
b'+' => {
|
||||
s = s.offset(1);
|
||||
false
|
||||
1.0
|
||||
}
|
||||
_ => false,
|
||||
_ => 1.0,
|
||||
};
|
||||
|
||||
if *s as u8 == b'0' && *s.offset(1) as u8 == b'x' {
|
||||
@@ -274,6 +276,54 @@ macro_rules! strto_float_impl {
|
||||
}
|
||||
}
|
||||
|
||||
let s_before_exponent = s;
|
||||
|
||||
let exponent = match (*s as u8, radix) {
|
||||
(b'e' | b'E', 10) | (b'p' | b'P', 16) => {
|
||||
s = s.offset(1);
|
||||
|
||||
let is_exponent_positive = match *s as u8 {
|
||||
b'-' => {
|
||||
s = s.offset(1);
|
||||
false
|
||||
}
|
||||
b'+' => {
|
||||
s = s.offset(1);
|
||||
true
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
|
||||
// Exponent digits are always in base 10.
|
||||
if (*s as u8 as char).is_digit(10) {
|
||||
let mut exponent_value = 0;
|
||||
|
||||
while let Some(digit) = (*s as u8 as char).to_digit(10) {
|
||||
exponent_value *= 10;
|
||||
exponent_value += digit;
|
||||
s = s.offset(1);
|
||||
}
|
||||
|
||||
let exponent_base = match radix {
|
||||
10 => 10u128,
|
||||
16 => 2u128,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if is_exponent_positive {
|
||||
Some(exponent_base.pow(exponent_value) as $type)
|
||||
} else {
|
||||
Some(1.0 / (exponent_base.pow(exponent_value) as $type))
|
||||
}
|
||||
} else {
|
||||
// Exponent had no valid digits after 'e'/'p' and '+'/'-', rollback
|
||||
s = s_before_exponent;
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if !endptr.is_null() {
|
||||
// This is stupid, but apparently strto* functions want
|
||||
// const input but mut output, yet the man page says
|
||||
@@ -282,10 +332,10 @@ macro_rules! strto_float_impl {
|
||||
*endptr = s as *mut _;
|
||||
}
|
||||
|
||||
if negative {
|
||||
-result
|
||||
if let Some(exponent) = exponent {
|
||||
result_sign * result * exponent
|
||||
} else {
|
||||
result
|
||||
result_sign * result
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -7,3 +7,165 @@ d: -5.300000 Endptr: ""
|
||||
d: 16.071045 Endptr: ""
|
||||
d: 1.136719 Endptr: ""
|
||||
d: 3.128906 Endptr: ""
|
||||
d: 100000.000000 Endptr: ""
|
||||
d: 100000.000000 Endptr: ""
|
||||
d: 0.000010 Endptr: ""
|
||||
d: 100000.000000 Endptr: " "
|
||||
d: 100000.000000 Endptr: " "
|
||||
d: 0.000010 Endptr: " "
|
||||
d: 10000000000.000000 Endptr: ""
|
||||
d: 1.000000 Endptr: "eXXXX"
|
||||
d: 1.000000 Endptr: "e"
|
||||
d: 1.000000 Endptr: "e "
|
||||
d: 10000000000.000000 Endptr: ""
|
||||
d: 1.000000 Endptr: "e+XXXX"
|
||||
d: 1.000000 Endptr: "e+"
|
||||
d: 1.000000 Endptr: "e+ "
|
||||
d: 0.000000 Endptr: ""
|
||||
d: 1.000000 Endptr: "e-XXXX"
|
||||
d: 1.000000 Endptr: "e-"
|
||||
d: 1.000000 Endptr: "e- "
|
||||
d: -100000.000000 Endptr: ""
|
||||
d: -100000.000000 Endptr: ""
|
||||
d: -0.000010 Endptr: ""
|
||||
d: -100000.000000 Endptr: " "
|
||||
d: -100000.000000 Endptr: " "
|
||||
d: -0.000010 Endptr: " "
|
||||
d: -10000000000.000000 Endptr: ""
|
||||
d: -1.000000 Endptr: "eXXXX"
|
||||
d: -1.000000 Endptr: "e"
|
||||
d: -1.000000 Endptr: "e "
|
||||
d: -10000000000.000000 Endptr: ""
|
||||
d: -1.000000 Endptr: "e+XXXX"
|
||||
d: -1.000000 Endptr: "e+"
|
||||
d: -1.000000 Endptr: "e+ "
|
||||
d: -0.000000 Endptr: ""
|
||||
d: -1.000000 Endptr: "e-XXXX"
|
||||
d: -1.000000 Endptr: "e-"
|
||||
d: -1.000000 Endptr: "e- "
|
||||
d: 1234000.000000 Endptr: ""
|
||||
d: 1234000.000000 Endptr: ""
|
||||
d: 0.000123 Endptr: ""
|
||||
d: 1234000.000000 Endptr: " "
|
||||
d: 1234000.000000 Endptr: " "
|
||||
d: 0.000123 Endptr: " "
|
||||
d: 123400000000.000000 Endptr: ""
|
||||
d: 12.340000 Endptr: "eXXXX"
|
||||
d: 12.340000 Endptr: "e"
|
||||
d: 12.340000 Endptr: "e "
|
||||
d: 123400000000.000000 Endptr: ""
|
||||
d: 12.340000 Endptr: "e+XXXX"
|
||||
d: 12.340000 Endptr: "e+"
|
||||
d: 12.340000 Endptr: "e+ "
|
||||
d: 0.000000 Endptr: ""
|
||||
d: 12.340000 Endptr: "e-XXXX"
|
||||
d: 12.340000 Endptr: "e-"
|
||||
d: 12.340000 Endptr: "e- "
|
||||
d: -1234000.000000 Endptr: ""
|
||||
d: -1234000.000000 Endptr: ""
|
||||
d: -0.000123 Endptr: ""
|
||||
d: -1234000.000000 Endptr: " "
|
||||
d: -1234000.000000 Endptr: " "
|
||||
d: -0.000123 Endptr: " "
|
||||
d: -123400000000.000000 Endptr: ""
|
||||
d: -12.340000 Endptr: "eXXXX"
|
||||
d: -12.340000 Endptr: "e"
|
||||
d: -12.340000 Endptr: "e "
|
||||
d: -123400000000.000000 Endptr: ""
|
||||
d: -12.340000 Endptr: "e+XXXX"
|
||||
d: -12.340000 Endptr: "e+"
|
||||
d: -12.340000 Endptr: "e+ "
|
||||
d: -0.000000 Endptr: ""
|
||||
d: -12.340000 Endptr: "e-XXXX"
|
||||
d: -12.340000 Endptr: "e-"
|
||||
d: -12.340000 Endptr: "e- "
|
||||
d: 192.000000 Endptr: ""
|
||||
d: -192.000000 Endptr: ""
|
||||
d: 0.005859 Endptr: ""
|
||||
d: -0.005859 Endptr: ""
|
||||
d: 10.000000 Endptr: ""
|
||||
d: 0.156250 Endptr: ""
|
||||
d: -10.000000 Endptr: ""
|
||||
d: -0.156250 Endptr: ""
|
||||
d: 16.062500 Endptr: ""
|
||||
d: 16.062500 Endptr: ""
|
||||
d: -16.062500 Endptr: ""
|
||||
d: -16.062500 Endptr: ""
|
||||
d: 0.500000 Endptr: ""
|
||||
d: 5.000000 Endptr: ""
|
||||
d: 50.000000 Endptr: ""
|
||||
d: 500.000000 Endptr: ""
|
||||
d: 5000.000000 Endptr: ""
|
||||
d: 50000.000000 Endptr: ""
|
||||
d: 500000.000000 Endptr: ""
|
||||
d: 5000000.000000 Endptr: ""
|
||||
d: 50000000.000000 Endptr: ""
|
||||
d: 500000000.000000 Endptr: ""
|
||||
d: 5000000000.000000 Endptr: ""
|
||||
d: 50000000000.000000 Endptr: ""
|
||||
d: 500000000000.000000 Endptr: ""
|
||||
d: 5000000000000.000000 Endptr: ""
|
||||
d: 50000000000000.000000 Endptr: ""
|
||||
d: 500000000000000.000000 Endptr: ""
|
||||
d: 5000000000000000.000000 Endptr: ""
|
||||
d: 50000000000000000.000000 Endptr: ""
|
||||
d: 500000000000000000.000000 Endptr: ""
|
||||
d: 5000000000000000000.000000 Endptr: ""
|
||||
d: 50000000000000000000.000000 Endptr: ""
|
||||
d: 500000000000000000000.000000 Endptr: ""
|
||||
d: 5000000000000000000000.000000 Endptr: ""
|
||||
d: 49999999999999995805696.000000 Endptr: ""
|
||||
d: 499999999999999991611392.000000 Endptr: ""
|
||||
d: 5000000000000000452984832.000000 Endptr: ""
|
||||
d: 50000000000000002382364672.000000 Endptr: ""
|
||||
d: 500000000000000006643777536.000000 Endptr: ""
|
||||
d: 4999999999999999791559868416.000000 Endptr: ""
|
||||
d: 49999999999999995716575428608.000000 Endptr: ""
|
||||
d: 500000000000000009942312419328.000000 Endptr: ""
|
||||
d: 4999999999999999817948147482624.000000 Endptr: ""
|
||||
d: 50000000000000002683081102196736.000000 Endptr: ""
|
||||
d: 499999999999999972787615493521408.000000 Endptr: ""
|
||||
d: 4999999999999999727876154935214080.000000 Endptr: ""
|
||||
d: 49999999999999998431683053958987776.000000 Endptr: ""
|
||||
d: 500000000000000021210318687008980992.000000 Endptr: ""
|
||||
d: 4999999999999999769381329101060571136.000000 Endptr: ""
|
||||
d: 49999999999999998874404911728017014784.000000 Endptr: ""
|
||||
d: -0.500000 Endptr: ""
|
||||
d: -5.000000 Endptr: ""
|
||||
d: -50.000000 Endptr: ""
|
||||
d: -500.000000 Endptr: ""
|
||||
d: -5000.000000 Endptr: ""
|
||||
d: -50000.000000 Endptr: ""
|
||||
d: -500000.000000 Endptr: ""
|
||||
d: -5000000.000000 Endptr: ""
|
||||
d: -50000000.000000 Endptr: ""
|
||||
d: -500000000.000000 Endptr: ""
|
||||
d: -5000000000.000000 Endptr: ""
|
||||
d: -50000000000.000000 Endptr: ""
|
||||
d: -500000000000.000000 Endptr: ""
|
||||
d: -5000000000000.000000 Endptr: ""
|
||||
d: -50000000000000.000000 Endptr: ""
|
||||
d: -500000000000000.000000 Endptr: ""
|
||||
d: -5000000000000000.000000 Endptr: ""
|
||||
d: -50000000000000000.000000 Endptr: ""
|
||||
d: -500000000000000000.000000 Endptr: ""
|
||||
d: -5000000000000000000.000000 Endptr: ""
|
||||
d: -50000000000000000000.000000 Endptr: ""
|
||||
d: -500000000000000000000.000000 Endptr: ""
|
||||
d: -5000000000000000000000.000000 Endptr: ""
|
||||
d: -49999999999999995805696.000000 Endptr: ""
|
||||
d: -499999999999999991611392.000000 Endptr: ""
|
||||
d: -5000000000000000452984832.000000 Endptr: ""
|
||||
d: -50000000000000002382364672.000000 Endptr: ""
|
||||
d: -500000000000000006643777536.000000 Endptr: ""
|
||||
d: -4999999999999999791559868416.000000 Endptr: ""
|
||||
d: -49999999999999995716575428608.000000 Endptr: ""
|
||||
d: -500000000000000009942312419328.000000 Endptr: ""
|
||||
d: -4999999999999999817948147482624.000000 Endptr: ""
|
||||
d: -50000000000000002683081102196736.000000 Endptr: ""
|
||||
d: -499999999999999972787615493521408.000000 Endptr: ""
|
||||
d: -4999999999999999727876154935214080.000000 Endptr: ""
|
||||
d: -49999999999999998431683053958987776.000000 Endptr: ""
|
||||
d: -500000000000000021210318687008980992.000000 Endptr: ""
|
||||
d: -4999999999999999769381329101060571136.000000 Endptr: ""
|
||||
d: -49999999999999998874404911728017014784.000000 Endptr: ""
|
||||
|
||||
+51
-1
@@ -10,7 +10,57 @@ int main(void) {
|
||||
char* inputs[] = {
|
||||
"a 1 hello", " 1 hello", "1 hello 2",
|
||||
"10.123", "010.123", "-5.3",
|
||||
"0x10.123", "0x1.23", "0x3.21"
|
||||
"0x10.123", "0x1.23", "0x3.21",
|
||||
|
||||
"1e5", "1e+5", "1e-5",
|
||||
"1e5 ", "1e+5 ", "1e-5 ",
|
||||
|
||||
"1e10", "1eXXXX", "1e", "1e ",
|
||||
"1e+10", "1e+XXXX", "1e+", "1e+ ",
|
||||
"1e-10", "1e-XXXX", "1e-", "1e- ",
|
||||
|
||||
"-1e5", "-1e+5", "-1e-5",
|
||||
"-1e5 ", "-1e+5 ", "-1e-5 ",
|
||||
|
||||
"-1e10", "-1eXXXX", "-1e", "-1e ",
|
||||
"-1e+10", "-1e+XXXX", "-1e+", "-1e+ ",
|
||||
"-1e-10", "-1e-XXXX", "-1e-", "-1e- ",
|
||||
|
||||
"12.34e5", "12.34e+5", "12.34e-5",
|
||||
"12.34e5 ", "12.34e+5 ", "12.34e-5 ",
|
||||
|
||||
"12.34e10", "12.34eXXXX", "12.34e", "12.34e ",
|
||||
"12.34e+10", "12.34e+XXXX", "12.34e+", "12.34e+ ",
|
||||
"12.34e-10", "12.34e-XXXX", "12.34e-", "12.34e- ",
|
||||
|
||||
"-12.34e5", "-12.34e+5", "-12.34e-5",
|
||||
"-12.34e5 ", "-12.34e+5 ", "-12.34e-5 ",
|
||||
|
||||
"-12.34e10", "-12.34eXXXX", "-12.34e", "-12.34e ",
|
||||
"-12.34e+10", "-12.34e+XXXX", "-12.34e+", "-12.34e+ ",
|
||||
"-12.34e-10", "-12.34e-XXXX", "-12.34e-", "-12.34e- ",
|
||||
|
||||
"0x0.3p10", "-0x0.3p10", "0x0.3p-5", "-0x0.3p-5",
|
||||
"0x1.4p3", "0x1.4p-3", "-0x1.4p3", "-0x1.4p-3",
|
||||
"0x10.1p0", "0x10.1p-0", "-0x10.1p0", "-0x10.1p-0",
|
||||
|
||||
"0.5e0", "0.5e1", "0.5e2", "0.5e3", "0.5e4",
|
||||
"0.5e5", "0.5e6", "0.5e7", "0.5e8", "0.5e9",
|
||||
"0.5e10", "0.5e11", "0.5e12", "0.5e13", "0.5e14",
|
||||
"0.5e15", "0.5e16", "0.5e17", "0.5e18", "0.5e19",
|
||||
"0.5e20", "0.5e21", "0.5e22", "0.5e23", "0.5e24",
|
||||
"0.5e25", "0.5e26", "0.5e27", "0.5e28", "0.5e29",
|
||||
"0.5e30", "0.5e31", "0.5e32", "0.5e33", "0.5e34",
|
||||
"0.5e35", "0.5e36", "0.5e37", "0.5e38",
|
||||
|
||||
"-0.5e0", "-0.5e1", "-0.5e2", "-0.5e3", "-0.5e4",
|
||||
"-0.5e5", "-0.5e6", "-0.5e7", "-0.5e8", "-0.5e9",
|
||||
"-0.5e10", "-0.5e11", "-0.5e12", "-0.5e13", "-0.5e14",
|
||||
"-0.5e15", "-0.5e16", "-0.5e17", "-0.5e18", "-0.5e19",
|
||||
"-0.5e20", "-0.5e21", "-0.5e22", "-0.5e23", "-0.5e24",
|
||||
"-0.5e25", "-0.5e26", "-0.5e27", "-0.5e28", "-0.5e29",
|
||||
"-0.5e30", "-0.5e31", "-0.5e32", "-0.5e33", "-0.5e34",
|
||||
"-0.5e35", "-0.5e36", "-0.5e37", "-0.5e38",
|
||||
};
|
||||
for (int i = 0; i < sizeof(inputs) / sizeof(char*); i += 1) {
|
||||
d = strtod(inputs[i], &endptr);
|
||||
|
||||
Reference in New Issue
Block a user