mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
Use hexponent to implement hex float parsing in wcstod
This teaches wcstod to parse hex floats like 0x1.5p3 via a forked version of hexponent. This support is necessary for printf.
This commit is contained in:
parent
74104f76ad
commit
14c5c94d01
3 changed files with 53 additions and 0 deletions
6
fish-rust/Cargo.lock
generated
6
fish-rust/Cargo.lock
generated
|
@ -374,6 +374,7 @@ dependencies = [
|
|||
"cxx-gen",
|
||||
"errno",
|
||||
"fast-float",
|
||||
"hexponent",
|
||||
"inventory",
|
||||
"libc",
|
||||
"lru",
|
||||
|
@ -462,6 +463,11 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "hexponent"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/fish-shell/hexponent?branch=fish#d2b97417d34adc9ea3ec954c69accc59828cbdb4"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
|
|
|
@ -8,6 +8,7 @@ rust-version = "1.67"
|
|||
widestring-suffix = { path = "./widestring-suffix/" }
|
||||
pcre2 = { git = "https://github.com/fish-shell/rust-pcre2", branch = "master", default-features = false, features = ["utf32"] }
|
||||
fast-float = { git = "https://github.com/fish-shell/fast-float-rust", branch="fish" }
|
||||
hexponent = { git = "https://github.com/fish-shell/hexponent", branch="fish" }
|
||||
printf-compat = { git = "https://github.com/fish-shell/printf-compat.git", branch="fish" }
|
||||
|
||||
autocxx = "0.23.1"
|
||||
|
|
|
@ -39,6 +39,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// If it's a hex float, use hexponent.
|
||||
if is_hex_float(chars.clone()) {
|
||||
let mut n = 0;
|
||||
let res = hexponent::parse_hex_float(chars, decimal_sep, &mut n);
|
||||
if res.is_ok() {
|
||||
*consumed = whitespace_skipped + n;
|
||||
}
|
||||
return res.map_err(hexponent_error);
|
||||
}
|
||||
|
||||
let ret = parse_partial_iter(chars.clone().fuse(), decimal_sep);
|
||||
if ret.is_err() {
|
||||
*consumed = 0;
|
||||
|
@ -63,6 +73,39 @@ where
|
|||
Ok(val)
|
||||
}
|
||||
|
||||
/// Check if a character iterator appears to be a hex float.
|
||||
/// That is, an optional + or -, followed by 0x or 0X, and a hex digit.
|
||||
pub fn is_hex_float<Chars: Iterator<Item = char>>(mut chars: Chars) -> bool {
|
||||
match chars.next() {
|
||||
Some('+' | '-') => {
|
||||
if chars.next() != Some('0') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Some('0') => (),
|
||||
_ => return false,
|
||||
};
|
||||
match chars.next() {
|
||||
Some('x') | Some('X') => (),
|
||||
_ => return false,
|
||||
};
|
||||
match chars.next() {
|
||||
Some(c) => c.is_ascii_hexdigit(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a a hexponent error to our error type.
|
||||
fn hexponent_error(e: hexponent::ParseError) -> Error {
|
||||
use hexponent::ParseErrorKind;
|
||||
match e.kind {
|
||||
ParseErrorKind::MissingPrefix
|
||||
| ParseErrorKind::MissingDigits
|
||||
| ParseErrorKind::MissingExponent => Error::InvalidChar,
|
||||
ParseErrorKind::ExponentOverflow => Error::Overflow,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#![allow(overflowing_literals)]
|
||||
|
@ -101,6 +144,9 @@ mod test {
|
|||
test_consumed("0.y", Ok(0.0), 2);
|
||||
test_consumed(".0y", Ok(0.0), 2);
|
||||
test_consumed("000,,,e1", Ok(0.0), 3);
|
||||
test_consumed("0x1", Ok(1.0), 3);
|
||||
test_consumed("0X1p2", Ok(4.0), 5);
|
||||
test_consumed("0X1P3", Ok(8.0), 5);
|
||||
test("000e1", Ok(0.0));
|
||||
test_consumed("000,1e1", Ok(0.0), 3);
|
||||
test("0", Ok(0.0));
|
||||
|
|
Loading…
Reference in a new issue