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,13 +88,47 @@ impl FromStr for Number {
|
||||||
if s.starts_with('+') {
|
if s.starts_with('+') {
|
||||||
s = &s[1..];
|
s = &s[1..];
|
||||||
}
|
}
|
||||||
|
let is_neg = s.starts_with('-');
|
||||||
|
|
||||||
match s.parse::<BigInt>() {
|
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) => {
|
Ok(n) => {
|
||||||
// If `s` is '-0', then `parse()` returns
|
// If `s` is '-0', then `parse()` returns
|
||||||
// `BigInt::zero()`, but we need to return
|
// `BigInt::zero()`, but we need to return
|
||||||
// `Number::MinusZero` instead.
|
// `Number::MinusZero` instead.
|
||||||
if n == BigInt::zero() && s.starts_with('-') {
|
if n == BigInt::zero() && is_neg {
|
||||||
Ok(Number::MinusZero)
|
Ok(Number::MinusZero)
|
||||||
} else {
|
} else {
|
||||||
Ok(Number::BigInt(n))
|
Ok(Number::BigInt(n))
|
||||||
|
@ -113,6 +147,7 @@ impl FromStr for Number {
|
||||||
uucore::execution_phrase(),
|
uucore::execution_phrase(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,69 @@
|
||||||
use crate::common::util::*;
|
use crate::common::util::*;
|
||||||
use std::io::Read;
|
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]
|
#[test]
|
||||||
fn test_rejects_nan() {
|
fn test_rejects_nan() {
|
||||||
let ts = TestScenario::new(util_name!());
|
let ts = TestScenario::new(util_name!());
|
||||||
|
|
Loading…
Reference in a new issue