1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 20:17:45 +00:00

uucore: format: num_parser: "infinity" string parsing

Not just "inf" is allowed, also "infinity".
This commit is contained in:
Nicolas Boichat 2025-03-20 15:07:26 +01:00
parent 5c06dd580b
commit 0cb37c83b9

View file

@ -5,7 +5,7 @@
//! Utilities for parsing numbers in various formats //! Utilities for parsing numbers in various formats
// spell-checker:ignore powf copysign prec inity bigdecimal extendedbigdecimal biguint // spell-checker:ignore powf copysign prec inity infinit bigdecimal extendedbigdecimal biguint
use bigdecimal::{ use bigdecimal::{
BigDecimal, BigDecimal,
@ -181,33 +181,34 @@ fn parse_special_value(
input: &str, input: &str,
negative: bool, negative: bool,
) -> Result<ExtendedBigDecimal, ExtendedParserError<'_, ExtendedBigDecimal>> { ) -> Result<ExtendedBigDecimal, ExtendedParserError<'_, ExtendedBigDecimal>> {
let prefix = input let input_lc = input.to_ascii_lowercase();
.chars()
.take(3) // Array of ("String to match", return value when sign positive, when sign negative)
.map(|c| c.to_ascii_lowercase()) const MATCH_TABLE: &[(&str, ExtendedBigDecimal)] = &[
.collect::<String>(); ("infinity", ExtendedBigDecimal::Infinity),
let special = match prefix.as_str() { ("inf", ExtendedBigDecimal::Infinity),
"inf" => { ("nan", ExtendedBigDecimal::Nan),
];
for (str, ebd) in MATCH_TABLE.iter() {
if input_lc.starts_with(str) {
let mut special = ebd.clone();
if negative { if negative {
ExtendedBigDecimal::MinusInfinity special = -special;
} else {
ExtendedBigDecimal::Infinity
} }
} let match_len = str.len();
"nan" => { return if input.len() == match_len {
if negative { Ok(special)
ExtendedBigDecimal::MinusNan
} else { } else {
ExtendedBigDecimal::Nan Err(ExtendedParserError::PartialMatch(
} special,
&input[match_len..],
))
};
} }
_ => return Err(ExtendedParserError::NotNumeric),
};
if input.len() == 3 {
Ok(special)
} else {
Err(ExtendedParserError::PartialMatch(special, &input[3..]))
} }
Err(ExtendedParserError::NotNumeric)
} }
// TODO: As highlighted by clippy, this function _is_ high cognitive complexity, jumps // TODO: As highlighted by clippy, this function _is_ high cognitive complexity, jumps
@ -467,6 +468,9 @@ mod tests {
assert_eq!(Ok(f64::INFINITY), f64::extended_parse("Inf")); assert_eq!(Ok(f64::INFINITY), f64::extended_parse("Inf"));
assert_eq!(Ok(f64::INFINITY), f64::extended_parse("InF")); assert_eq!(Ok(f64::INFINITY), f64::extended_parse("InF"));
assert_eq!(Ok(f64::INFINITY), f64::extended_parse("INF")); assert_eq!(Ok(f64::INFINITY), f64::extended_parse("INF"));
assert_eq!(Ok(f64::INFINITY), f64::extended_parse("infinity"));
assert_eq!(Ok(f64::INFINITY), f64::extended_parse("+infiNIty"));
assert_eq!(Ok(f64::NEG_INFINITY), f64::extended_parse("-INfinity"));
assert!(f64::extended_parse("NaN").unwrap().is_nan()); assert!(f64::extended_parse("NaN").unwrap().is_nan());
assert!(f64::extended_parse("NaN").unwrap().is_sign_positive()); assert!(f64::extended_parse("NaN").unwrap().is_sign_positive());
assert!(f64::extended_parse("+NaN").unwrap().is_nan()); assert!(f64::extended_parse("+NaN").unwrap().is_nan());
@ -477,8 +481,10 @@ mod tests {
assert!(f64::extended_parse("nan").unwrap().is_sign_positive()); assert!(f64::extended_parse("nan").unwrap().is_sign_positive());
assert!(f64::extended_parse("NAN").unwrap().is_nan()); assert!(f64::extended_parse("NAN").unwrap().is_nan());
assert!(f64::extended_parse("NAN").unwrap().is_sign_positive()); assert!(f64::extended_parse("NAN").unwrap().is_sign_positive());
assert!(matches!(f64::extended_parse("-infinity"), assert!(matches!(f64::extended_parse("-infinit"),
Err(ExtendedParserError::PartialMatch(f, "inity")) if f == f64::NEG_INFINITY)); Err(ExtendedParserError::PartialMatch(f, "init")) if f == f64::NEG_INFINITY));
assert!(matches!(f64::extended_parse("-infinity00"),
Err(ExtendedParserError::PartialMatch(f, "00")) if f == f64::NEG_INFINITY));
assert!(f64::extended_parse(&format!("{}", u64::MAX)).is_ok()); assert!(f64::extended_parse(&format!("{}", u64::MAX)).is_ok());
assert!(f64::extended_parse(&format!("{}", i64::MIN)).is_ok()); assert!(f64::extended_parse(&format!("{}", i64::MIN)).is_ok());
} }