mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 13:53: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",
|
"cxx-gen",
|
||||||
"errno",
|
"errno",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
|
"hexponent",
|
||||||
"inventory",
|
"inventory",
|
||||||
"libc",
|
"libc",
|
||||||
"lru",
|
"lru",
|
||||||
|
@ -462,6 +463,11 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hexponent"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "git+https://github.com/fish-shell/hexponent?branch=fish#d2b97417d34adc9ea3ec954c69accc59828cbdb4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
|
|
@ -8,6 +8,7 @@ rust-version = "1.67"
|
||||||
widestring-suffix = { path = "./widestring-suffix/" }
|
widestring-suffix = { path = "./widestring-suffix/" }
|
||||||
pcre2 = { git = "https://github.com/fish-shell/rust-pcre2", branch = "master", default-features = false, features = ["utf32"] }
|
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" }
|
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" }
|
printf-compat = { git = "https://github.com/fish-shell/printf-compat.git", branch="fish" }
|
||||||
|
|
||||||
autocxx = "0.23.1"
|
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);
|
let ret = parse_partial_iter(chars.clone().fuse(), decimal_sep);
|
||||||
if ret.is_err() {
|
if ret.is_err() {
|
||||||
*consumed = 0;
|
*consumed = 0;
|
||||||
|
@ -63,6 +73,39 @@ where
|
||||||
Ok(val)
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
#![allow(overflowing_literals)]
|
#![allow(overflowing_literals)]
|
||||||
|
@ -101,6 +144,9 @@ mod test {
|
||||||
test_consumed("0.y", Ok(0.0), 2);
|
test_consumed("0.y", Ok(0.0), 2);
|
||||||
test_consumed(".0y", Ok(0.0), 2);
|
test_consumed(".0y", Ok(0.0), 2);
|
||||||
test_consumed("000,,,e1", Ok(0.0), 3);
|
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("000e1", Ok(0.0));
|
||||||
test_consumed("000,1e1", Ok(0.0), 3);
|
test_consumed("000,1e1", Ok(0.0), 3);
|
||||||
test("0", Ok(0.0));
|
test("0", Ok(0.0));
|
||||||
|
|
Loading…
Reference in a new issue