mirror of
https://github.com/uutils/coreutils
synced 2024-11-16 17:58:06 +00:00
Merge pull request #2701 from vulppine/seq-hex
seq: Adds hexadecimal integer parsing
This commit is contained in:
commit
03a037e8ea
2 changed files with 112 additions and 14 deletions
|
@ -88,30 +88,65 @@ impl FromStr for Number {
|
|||
if s.starts_with('+') {
|
||||
s = &s[1..];
|
||||
}
|
||||
let is_neg = s.starts_with('-');
|
||||
|
||||
match s.parse::<BigInt>() {
|
||||
Ok(n) => {
|
||||
// If `s` is '-0', then `parse()` returns
|
||||
// `BigInt::zero()`, but we need to return
|
||||
// `Number::MinusZero` instead.
|
||||
if n == BigInt::zero() && s.starts_with('-') {
|
||||
Ok(Number::MinusZero)
|
||||
} else {
|
||||
Ok(Number::BigInt(n))
|
||||
match s.to_lowercase().find("0x") {
|
||||
Some(i) if i <= 1 => match &s.as_bytes()[i + 2] {
|
||||
b'-' | b'+' => Err(format!(
|
||||
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
// TODO: hexadecimal floating point parsing (see #2660)
|
||||
b'.' => Err(format!(
|
||||
"NotImplemented: hexadecimal floating point numbers: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
_ => {
|
||||
let num = BigInt::from_str_radix(&s[i + 2..], 16)
|
||||
.map_err(|_| format!(
|
||||
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
))?;
|
||||
match (is_neg, num == BigInt::zero()) {
|
||||
(true, true) => Ok(Number::MinusZero),
|
||||
(true, false) => Ok(Number::BigInt(-num)),
|
||||
(false, _) => Ok(Number::BigInt(num)),
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(_) => Err(format!(
|
||||
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
|
||||
None => match s.parse::<BigInt>() {
|
||||
Ok(n) => {
|
||||
// If `s` is '-0', then `parse()` returns
|
||||
// `BigInt::zero()`, but we need to return
|
||||
// `Number::MinusZero` instead.
|
||||
if n == BigInt::zero() && is_neg {
|
||||
Ok(Number::MinusZero)
|
||||
} else {
|
||||
Ok(Number::BigInt(n))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => match s.parse::<f64>() {
|
||||
Ok(value) if value.is_nan() => Err(format!(
|
||||
Err(_) => match s.parse::<f64>() {
|
||||
Ok(value) if value.is_nan() => Err(format!(
|
||||
"invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
Ok(value) => Ok(Number::F64(value)),
|
||||
Err(_) => Err(format!(
|
||||
Ok(value) => Ok(Number::F64(value)),
|
||||
Err(_) => Err(format!(
|
||||
"invalid floating point argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,69 @@
|
|||
use crate::common::util::*;
|
||||
use std::io::Read;
|
||||
|
||||
#[test]
|
||||
fn test_hex_rejects_sign_after_identifier() {
|
||||
new_ucmd!()
|
||||
.args(&["0x-123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '0x-123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
new_ucmd!()
|
||||
.args(&["0x+123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '0x+123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
new_ucmd!()
|
||||
.args(&["-0x-123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '-0x-123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
new_ucmd!()
|
||||
.args(&["-0x+123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '-0x+123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex_lowercase_uppercase() {
|
||||
new_ucmd!()
|
||||
.args(&["0xa", "0xA"])
|
||||
.succeeds()
|
||||
.stdout_is("10\n");
|
||||
new_ucmd!()
|
||||
.args(&["0Xa", "0XA"])
|
||||
.succeeds()
|
||||
.stdout_is("10\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex_big_number() {
|
||||
new_ucmd!()
|
||||
.args(&[
|
||||
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"0x100000000000000000000000000000000",
|
||||
])
|
||||
.succeeds()
|
||||
.stdout_is(
|
||||
"340282366920938463463374607431768211455\n340282366920938463463374607431768211456\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex_identifier_in_wrong_place() {
|
||||
new_ucmd!()
|
||||
.args(&["1234ABCD0x"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '1234ABCD0x'")
|
||||
.stderr_contains("for more information.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rejects_nan() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
|
|
Loading…
Reference in a new issue