mirror of
https://github.com/uutils/coreutils
synced 2024-11-10 07:04:16 +00:00
od: several small changes after review
* update status in README.md * enable busybox tests Adding `CONFIG_DESKTOP` and `CONFIG_LONG_OPTS` to busybox config. These flags also enable other tests, but those utilities are not included in `TEST_PROGS`. (eg. awk) * fix whitespace and small issues * fix Eq imp for FormatWriter on nightly + beta * fix indention in multifilereader.rs * fix intermittent errors in tests
This commit is contained in:
parent
99f70ba648
commit
2550e0f3c7
16 changed files with 180 additions and 247 deletions
|
@ -1,2 +1,4 @@
|
||||||
CONFIG_FEATURE_FANCY_HEAD=y
|
CONFIG_FEATURE_FANCY_HEAD=y
|
||||||
CONFIG_UNICODE_SUPPORT=y
|
CONFIG_UNICODE_SUPPORT=y
|
||||||
|
CONFIG_DESKTOP=y
|
||||||
|
CONFIG_LONG_OPTS=y
|
||||||
|
|
|
@ -201,7 +201,7 @@ To do
|
||||||
* [x] nohup
|
* [x] nohup
|
||||||
* [x] nproc
|
* [x] nproc
|
||||||
* [ ] numfmt
|
* [ ] numfmt
|
||||||
* [ ] od (in progress, needs lots of work)
|
* [ ] od (almost complete, `--strings` and 128-bit datatypes are missing)
|
||||||
* [x] paste
|
* [x] paste
|
||||||
* [x] pathchk
|
* [x] pathchk
|
||||||
* [x] pinky
|
* [x] pinky
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Copy, Eq)]
|
#[derive(Copy)]
|
||||||
pub enum FormatWriter {
|
pub enum FormatWriter {
|
||||||
IntWriter(fn(u64) -> String),
|
IntWriter(fn(u64) -> String),
|
||||||
FloatWriter(fn(f64) -> String),
|
FloatWriter(fn(f64) -> String),
|
||||||
|
@ -27,6 +27,8 @@ impl PartialEq for FormatWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for FormatWriter {}
|
||||||
|
|
||||||
impl fmt::Debug for FormatWriter {
|
impl fmt::Debug for FormatWriter {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -26,12 +26,11 @@ pub struct InputDecoder<'a, I> where I: 'a {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I> InputDecoder<'a, I> {
|
impl<'a, I> InputDecoder<'a, I> {
|
||||||
/// Creates a new `InputDecoder` with an allocated buffer of `normal_length`+`peek_length` bytes.
|
/// Creates a new `InputDecoder` with an allocated buffer of `normal_length` + `peek_length` bytes.
|
||||||
/// `byte_order` determines how to read multibyte formats from the buffer.
|
/// `byte_order` determines how to read multibyte formats from the buffer.
|
||||||
pub fn new(input: &mut I, normal_length: usize, peek_length: usize, byte_order: ByteOrder) -> InputDecoder<I> {
|
pub fn new(input: &mut I, normal_length: usize, peek_length: usize, byte_order: ByteOrder) -> InputDecoder<I> {
|
||||||
|
let mut bytes: Vec<u8> = Vec::with_capacity(normal_length + peek_length);
|
||||||
let mut bytes: Vec<u8> = Vec::with_capacity(normal_length+peek_length);
|
unsafe { bytes.set_len(normal_length + peek_length); } // fast but uninitialized
|
||||||
unsafe { bytes.set_len(normal_length+peek_length); } // fast but uninitialized
|
|
||||||
|
|
||||||
InputDecoder {
|
InputDecoder {
|
||||||
input: input,
|
input: input,
|
||||||
|
@ -45,7 +44,7 @@ impl<'a, I> InputDecoder<'a, I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a, I> InputDecoder<'a, I> where I : PeekRead {
|
impl<'a, I> InputDecoder<'a, I> where I: PeekRead {
|
||||||
/// calls `peek_read` on the internal stream to (re)fill the buffer. Returns a
|
/// calls `peek_read` on the internal stream to (re)fill the buffer. Returns a
|
||||||
/// MemoryDecoder providing access to the result or returns an i/o error.
|
/// MemoryDecoder providing access to the result or returns an i/o error.
|
||||||
pub fn peek_read(&mut self) -> io::Result<MemoryDecoder> {
|
pub fn peek_read(&mut self) -> io::Result<MemoryDecoder> {
|
||||||
|
@ -66,7 +65,7 @@ impl<'a, I> InputDecoder<'a, I> where I : PeekRead {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I> HasError for InputDecoder<'a, I> where I : HasError {
|
impl<'a, I> HasError for InputDecoder<'a, I> where I: HasError {
|
||||||
/// calls has_error on the internal stream.
|
/// calls has_error on the internal stream.
|
||||||
fn has_error(&self) -> bool {
|
fn has_error(&self) -> bool {
|
||||||
self.input.has_error()
|
self.input.has_error()
|
||||||
|
@ -112,7 +111,7 @@ impl<'a> MemoryDecoder<'a> {
|
||||||
|
|
||||||
/// Returns a slice to the internal buffer including the peek data starting at `start`.
|
/// Returns a slice to the internal buffer including the peek data starting at `start`.
|
||||||
pub fn get_full_buffer(&self, start: usize) -> &[u8] {
|
pub fn get_full_buffer(&self, start: usize) -> &[u8] {
|
||||||
&self.data[start..self.used_normal_length+self.used_peek_length]
|
&self.data[start..self.used_normal_length + self.used_peek_length]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a u8/u16/u32/u64 from the internal buffer at position `start`.
|
/// Returns a u8/u16/u32/u64 from the internal buffer at position `start`.
|
||||||
|
@ -147,8 +146,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn smoke_test() {
|
fn smoke_test() {
|
||||||
let data = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xff, 0xff];
|
let data = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xff, 0xff];
|
||||||
let mut input=PeekReader::new(Cursor::new(&data));
|
let mut input = PeekReader::new(Cursor::new(&data));
|
||||||
let mut sut=InputDecoder::new(&mut input, 8, 2, ByteOrder::Little);
|
let mut sut = InputDecoder::new(&mut input, 8, 2, ByteOrder::Little);
|
||||||
|
|
||||||
match sut.peek_read() {
|
match sut.peek_read() {
|
||||||
Ok(mut mem) => {
|
Ok(mut mem) => {
|
||||||
|
@ -165,7 +164,7 @@ mod tests {
|
||||||
|
|
||||||
let mut copy: Vec<u8> = Vec::new();
|
let mut copy: Vec<u8> = Vec::new();
|
||||||
mem.clone_buffer(&mut copy);
|
mem.clone_buffer(&mut copy);
|
||||||
assert_eq!(vec!{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0}, copy);
|
assert_eq!(vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0], copy);
|
||||||
|
|
||||||
mem.zero_out_buffer(7, 8);
|
mem.zero_out_buffer(7, 8);
|
||||||
assert_eq!(&[0, 0, 0xff, 0xff], mem.get_full_buffer(6));
|
assert_eq!(&[0, 0, 0xff, 0xff], mem.get_full_buffer(6));
|
||||||
|
|
|
@ -62,8 +62,7 @@ impl FailingMockStream {
|
||||||
fn error(&mut self) -> Result<usize> {
|
fn error(&mut self) -> Result<usize> {
|
||||||
if self.repeat_count == 0 {
|
if self.repeat_count == 0 {
|
||||||
return Ok(0)
|
return Ok(0)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if self.repeat_count > 0 {
|
if self.repeat_count > 0 {
|
||||||
self.repeat_count -= 1;
|
self.repeat_count -= 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::io::Write;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
pub enum InputSource<'a> {
|
pub enum InputSource<'a> {
|
||||||
FileName(&'a str ),
|
FileName(&'a str),
|
||||||
Stdin,
|
Stdin,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Stream(Box<io::Read>),
|
Stream(Box<io::Read>),
|
||||||
|
@ -31,26 +31,26 @@ impl<'b> MultifileReader<'b> {
|
||||||
any_err: false,
|
any_err: false,
|
||||||
};
|
};
|
||||||
mf.next_file();
|
mf.next_file();
|
||||||
return mf;
|
mf
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_file(&mut self) {
|
fn next_file(&mut self) {
|
||||||
// loop retries with subsequent files if err - normally 'loops' once
|
// loop retries with subsequent files if err - normally 'loops' once
|
||||||
loop {
|
loop {
|
||||||
if self.ni.len() == 0 {
|
if self.ni.len() == 0 {
|
||||||
self.curr_file = None;
|
self.curr_file = None;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
match self.ni.remove(0) {
|
match self.ni.remove(0) {
|
||||||
InputSource::Stdin => {
|
InputSource::Stdin => {
|
||||||
self.curr_file = Some(Box::new(BufReader::new(std::io::stdin())));
|
self.curr_file = Some(Box::new(BufReader::new(std::io::stdin())));
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
InputSource::FileName(fname) => {
|
InputSource::FileName(fname) => {
|
||||||
match File::open(fname) {
|
match File::open(fname) {
|
||||||
Ok(f) => {
|
Ok(f) => {
|
||||||
self.curr_file = Some(Box::new(BufReader::new(f)));
|
self.curr_file = Some(Box::new(BufReader::new(f)));
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// If any file can't be opened,
|
// If any file can't be opened,
|
||||||
|
@ -66,7 +66,7 @@ impl<'b> MultifileReader<'b> {
|
||||||
}
|
}
|
||||||
InputSource::Stream(s) => {
|
InputSource::Stream(s) => {
|
||||||
self.curr_file = Some(s);
|
self.curr_file = Some(s);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,6 @@ impl<'b> MultifileReader<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> io::Read for MultifileReader<'b> {
|
impl<'b> io::Read for MultifileReader<'b> {
|
||||||
|
|
||||||
// Fill buf with bytes read from the list of files
|
// Fill buf with bytes read from the list of files
|
||||||
// Returns Ok(<number of bytes read>)
|
// Returns Ok(<number of bytes read>)
|
||||||
// Handles io errors itself, thus always returns OK
|
// Handles io errors itself, thus always returns OK
|
||||||
|
@ -192,5 +191,4 @@ mod tests {
|
||||||
assert_eq!(sut.read(v.as_mut()).unwrap(), 3);
|
assert_eq!(sut.read(v.as_mut()).unwrap(), 3);
|
||||||
assert_eq!(v, [0x42, 0x43, 0x44, 0x64, 0x41]); // last two bytes are not overwritten
|
assert_eq!(v, [0x42, 0x43, 0x44, 0x64, 0x41]); // last two bytes are not overwritten
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
22
src/od/od.rs
22
src/od/od.rs
|
@ -147,8 +147,8 @@ fn create_getopts_options() -> getopts::Options {
|
||||||
|
|
||||||
struct OdOptions {
|
struct OdOptions {
|
||||||
byte_order: ByteOrder,
|
byte_order: ByteOrder,
|
||||||
skip_bytes : usize,
|
skip_bytes: usize,
|
||||||
read_bytes : Option<usize>,
|
read_bytes: Option<usize>,
|
||||||
label: Option<usize>,
|
label: Option<usize>,
|
||||||
input_strings: Vec<String>,
|
input_strings: Vec<String>,
|
||||||
formats: Vec<ParsedFormatterItemInfo>,
|
formats: Vec<ParsedFormatterItemInfo>,
|
||||||
|
@ -187,7 +187,7 @@ impl OdOptions {
|
||||||
Ok(CommandLineInputs::FileAndOffset((f, s, l))) => {
|
Ok(CommandLineInputs::FileAndOffset((f, s, l))) => {
|
||||||
skip_bytes = s;
|
skip_bytes = s;
|
||||||
label = l;
|
label = l;
|
||||||
vec!{f}
|
vec![f]
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(format!("Invalid inputs: {}", e));
|
return Err(format!("Invalid inputs: {}", e));
|
||||||
|
@ -311,7 +311,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
/// Loops through the input line by line, calling print_bytes to take care of the output.
|
/// Loops through the input line by line, calling print_bytes to take care of the output.
|
||||||
fn odfunc<I>(input_offset: &mut InputOffset, input_decoder: &mut InputDecoder<I>,
|
fn odfunc<I>(input_offset: &mut InputOffset, input_decoder: &mut InputDecoder<I>,
|
||||||
output_info: &OutputInfo) -> i32
|
output_info: &OutputInfo) -> i32
|
||||||
where I : PeekRead+HasError {
|
where I: PeekRead + HasError {
|
||||||
let mut duplicate_line = false;
|
let mut duplicate_line = false;
|
||||||
let mut previous_bytes: Vec<u8> = Vec::new();
|
let mut previous_bytes: Vec<u8> = Vec::new();
|
||||||
let line_bytes = output_info.byte_size_line;
|
let line_bytes = output_info.byte_size_line;
|
||||||
|
@ -321,7 +321,7 @@ fn odfunc<I>(input_offset: &mut InputOffset, input_decoder: &mut InputDecoder<I>
|
||||||
|
|
||||||
match input_decoder.peek_read() {
|
match input_decoder.peek_read() {
|
||||||
Ok(mut memory_decoder) => {
|
Ok(mut memory_decoder) => {
|
||||||
let length=memory_decoder.length();
|
let length = memory_decoder.length();
|
||||||
|
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
input_offset.print_final_offset();
|
input_offset.print_final_offset();
|
||||||
|
@ -346,8 +346,7 @@ fn odfunc<I>(input_offset: &mut InputOffset, input_decoder: &mut InputDecoder<I>
|
||||||
duplicate_line = true;
|
duplicate_line = true;
|
||||||
println!("*");
|
println!("*");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
duplicate_line = false;
|
duplicate_line = false;
|
||||||
if length == line_bytes {
|
if length == line_bytes {
|
||||||
// save a copy of the input unless it is the last line
|
// save a copy of the input unless it is the last line
|
||||||
|
@ -409,15 +408,14 @@ fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder, output_info: &Output
|
||||||
output_text.push_str(&format!("{:>width$} {}",
|
output_text.push_str(&format!("{:>width$} {}",
|
||||||
"",
|
"",
|
||||||
format_ascii_dump(input_decoder.get_buffer(0)),
|
format_ascii_dump(input_decoder.get_buffer(0)),
|
||||||
width=missing_spacing));
|
width = missing_spacing));
|
||||||
}
|
}
|
||||||
|
|
||||||
if first {
|
if first {
|
||||||
print!("{}", prefix); // print offset
|
print!("{}", prefix); // print offset
|
||||||
// if printing in multiple formats offset is printed only once
|
// if printing in multiple formats offset is printed only once
|
||||||
first = false;
|
first = false;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// this takes the space of the file offset on subsequent
|
// this takes the space of the file offset on subsequent
|
||||||
// lines of multi-format rasters.
|
// lines of multi-format rasters.
|
||||||
print!("{:>width$}", "", width=prefix.chars().count());
|
print!("{:>width$}", "", width=prefix.chars().count());
|
||||||
|
@ -426,13 +424,13 @@ fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder, output_info: &Output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns a reader implementing `PeekRead+Read+HasError` providing the combined input
|
/// returns a reader implementing `PeekRead + Read + HasError` providing the combined input
|
||||||
///
|
///
|
||||||
/// `skip_bytes` is the number of bytes skipped from the input
|
/// `skip_bytes` is the number of bytes skipped from the input
|
||||||
/// `read_bytes` is an optinal limit to the number of bytes to read
|
/// `read_bytes` is an optinal limit to the number of bytes to read
|
||||||
fn open_input_peek_reader<'a>(input_strings: &'a Vec<String>, skip_bytes: usize,
|
fn open_input_peek_reader<'a>(input_strings: &'a Vec<String>, skip_bytes: usize,
|
||||||
read_bytes: Option<usize>) -> PeekReader<PartialReader<MultifileReader<'a>>> {
|
read_bytes: Option<usize>) -> PeekReader<PartialReader<MultifileReader<'a>>> {
|
||||||
// should return "impl PeekRead+Read+HasError" when supported in (stable) rust
|
// should return "impl PeekRead + Read + HasError" when supported in (stable) rust
|
||||||
let inputs = input_strings
|
let inputs = input_strings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|w| match w as &str {
|
.map(|w| match w as &str {
|
||||||
|
|
|
@ -49,7 +49,6 @@ impl OutputInfo {
|
||||||
|
|
||||||
/// Creates a new `OutputInfo` based on the parameters
|
/// Creates a new `OutputInfo` based on the parameters
|
||||||
pub fn new(line_bytes: usize, formats: &[ParsedFormatterItemInfo], output_duplicates: bool) -> OutputInfo {
|
pub fn new(line_bytes: usize, formats: &[ParsedFormatterItemInfo], output_duplicates: bool) -> OutputInfo {
|
||||||
|
|
||||||
let byte_size_block = formats.iter().fold(1, |max, next| cmp::max(max, next.formatter_item_info.byte_size));
|
let byte_size_block = formats.iter().fold(1, |max, next| cmp::max(max, next.formatter_item_info.byte_size));
|
||||||
let print_width_block = formats
|
let print_width_block = formats
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -129,7 +128,6 @@ impl OutputInfo {
|
||||||
/// Increase MAX_BYTES_PER_UNIT to allow larger types.
|
/// Increase MAX_BYTES_PER_UNIT to allow larger types.
|
||||||
fn calculate_alignment(sf: &TypeSizeInfo, byte_size_block: usize,
|
fn calculate_alignment(sf: &TypeSizeInfo, byte_size_block: usize,
|
||||||
print_width_block: usize) -> [usize; MAX_BYTES_PER_UNIT] {
|
print_width_block: usize) -> [usize; MAX_BYTES_PER_UNIT] {
|
||||||
|
|
||||||
if byte_size_block > MAX_BYTES_PER_UNIT {
|
if byte_size_block > MAX_BYTES_PER_UNIT {
|
||||||
panic!("{}-bits types are unsupported. Current max={}-bits.",
|
panic!("{}-bits types are unsupported. Current max={}-bits.",
|
||||||
8 * byte_size_block,
|
8 * byte_size_block,
|
||||||
|
@ -181,7 +179,6 @@ impl TypeSizeInfo for TypeInfo {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_calculate_alignment() {
|
fn test_calculate_alignment() {
|
||||||
|
|
||||||
// For this example `byte_size_block` is 8 and 'print_width_block' is 23:
|
// For this example `byte_size_block` is 8 and 'print_width_block' is 23:
|
||||||
// 1777777777777777777777 1777777777777777777777
|
// 1777777777777777777777 1777777777777777777777
|
||||||
// 4294967295 4294967295 4294967295 4294967295
|
// 4294967295 4294967295 4294967295 4294967295
|
||||||
|
@ -214,31 +211,31 @@ fn test_calculate_alignment() {
|
||||||
|
|
||||||
// 9 tests where 8 .. 16 spaces are spread across 8 positions
|
// 9 tests where 8 .. 16 spaces are spread across 8 positions
|
||||||
assert_eq!([1, 1, 1, 1, 1, 1, 1, 1],
|
assert_eq!([1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+8));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 8));
|
||||||
assert_eq!([2, 1, 1, 1, 1, 1, 1, 1],
|
assert_eq!([2, 1, 1, 1, 1, 1, 1, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+9));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 9));
|
||||||
assert_eq!([2, 1, 1, 1, 2, 1, 1, 1],
|
assert_eq!([2, 1, 1, 1, 2, 1, 1, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+10));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 10));
|
||||||
assert_eq!([3, 1, 1, 1, 2, 1, 1, 1],
|
assert_eq!([3, 1, 1, 1, 2, 1, 1, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+11));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 11));
|
||||||
assert_eq!([2, 1, 2, 1, 2, 1, 2, 1],
|
assert_eq!([2, 1, 2, 1, 2, 1, 2, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+12));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 12));
|
||||||
assert_eq!([3, 1, 2, 1, 2, 1, 2, 1],
|
assert_eq!([3, 1, 2, 1, 2, 1, 2, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+13));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 13));
|
||||||
assert_eq!([3, 1, 2, 1, 3, 1, 2, 1],
|
assert_eq!([3, 1, 2, 1, 3, 1, 2, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+14));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 14));
|
||||||
assert_eq!([4, 1, 2, 1, 3, 1, 2, 1],
|
assert_eq!([4, 1, 2, 1, 3, 1, 2, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+15));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 15));
|
||||||
assert_eq!([2, 2, 2, 2, 2, 2, 2, 2],
|
assert_eq!([2, 2, 2, 2, 2, 2, 2, 2],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+16));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 16));
|
||||||
|
|
||||||
// 4 tests where 15 spaces are spread across 8, 4, 2 or 1 position(s)
|
// 4 tests where 15 spaces are spread across 8, 4, 2 or 1 position(s)
|
||||||
assert_eq!([4, 1, 2, 1, 3, 1, 2, 1],
|
assert_eq!([4, 1, 2, 1, 3, 1, 2, 1],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+15));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16 + 15));
|
||||||
assert_eq!([5, 0, 3, 0, 4, 0, 3, 0],
|
assert_eq!([5, 0, 3, 0, 4, 0, 3, 0],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:2, print_width:4}, 8, 16+15));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:2, print_width:4}, 8, 16 + 15));
|
||||||
assert_eq!([8, 0, 0, 0, 7, 0, 0, 0],
|
assert_eq!([8, 0, 0, 0, 7, 0, 0, 0],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:4, print_width:8}, 8, 16+15));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:4, print_width:8}, 8, 16 + 15));
|
||||||
assert_eq!([15, 0, 0, 0, 0, 0, 0, 0],
|
assert_eq!([15, 0, 0, 0, 0, 0, 0, 0],
|
||||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:8, print_width:16}, 8, 16+15));
|
OutputInfo::calculate_alignment(&TypeInfo{byte_size:8, print_width:16}, 8, 16 + 15));
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,7 @@ pub fn parse_format_flags(args: &Vec<String>) -> Result<Vec<ParsedFormatterItemI
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
expect_type_string = false;
|
expect_type_string = false;
|
||||||
}
|
} else if arg.starts_with("--") {
|
||||||
else if arg.starts_with("--") {
|
|
||||||
if arg.len() == 2 {
|
if arg.len() == 2 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -130,26 +129,20 @@ pub fn parse_format_flags(args: &Vec<String>) -> Result<Vec<ParsedFormatterItemI
|
||||||
if arg == "--format" {
|
if arg == "--format" {
|
||||||
expect_type_string = true;
|
expect_type_string = true;
|
||||||
}
|
}
|
||||||
}
|
} else if arg.starts_with("-") {
|
||||||
else if arg.starts_with("-") {
|
|
||||||
let mut flags = arg.chars().skip(1);
|
let mut flags = arg.chars().skip(1);
|
||||||
let mut format_spec = String::new();
|
let mut format_spec = String::new();
|
||||||
while let Some(c) = flags.next() {
|
while let Some(c) = flags.next() {
|
||||||
if expect_type_string {
|
if expect_type_string {
|
||||||
format_spec.push(c);
|
format_spec.push(c);
|
||||||
}
|
} else if od_argument_with_option(c) {
|
||||||
else if od_argument_with_option(c) {
|
|
||||||
break;
|
break;
|
||||||
}
|
} else if c == 't' {
|
||||||
else if c=='t' {
|
|
||||||
expect_type_string = true;
|
expect_type_string = true;
|
||||||
}
|
} else {
|
||||||
else {
|
// not every option is a format
|
||||||
match od_argument_traditional_format(c) {
|
if let Some(r) = od_argument_traditional_format(c) {
|
||||||
None => {} // not every option is a format
|
formats.push(ParsedFormatterItemInfo::new(r, false))
|
||||||
Some(r) => {
|
|
||||||
formats.push(ParsedFormatterItemInfo::new(r, false))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +210,6 @@ fn format_type_category(t: FormatType) -> FormatTypeCategory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_format_size_char(ch: Option<char>, format_type: FormatTypeCategory, byte_size: &mut u8) -> bool {
|
fn is_format_size_char(ch: Option<char>, format_type: FormatTypeCategory, byte_size: &mut u8) -> bool {
|
||||||
|
|
||||||
match (format_type, ch) {
|
match (format_type, ch) {
|
||||||
(FormatTypeCategory::Integer, Some('C')) => {
|
(FormatTypeCategory::Integer, Some('C')) => {
|
||||||
*byte_size = 1;
|
*byte_size = 1;
|
||||||
|
@ -274,7 +266,7 @@ fn is_format_dump_char(ch: Option<char>, show_ascii_dump: &mut bool) -> bool {
|
||||||
fn parse_type_string(params: &String) -> Result<Vec<ParsedFormatterItemInfo>, String> {
|
fn parse_type_string(params: &String) -> Result<Vec<ParsedFormatterItemInfo>, String> {
|
||||||
let mut formats = Vec::new();
|
let mut formats = Vec::new();
|
||||||
|
|
||||||
let mut chars=params.chars();
|
let mut chars = params.chars();
|
||||||
let mut ch = chars.next();
|
let mut ch = chars.next();
|
||||||
|
|
||||||
while ch.is_some() {
|
while ch.is_some() {
|
||||||
|
@ -294,14 +286,13 @@ fn parse_type_string(params: &String) -> Result<Vec<ParsedFormatterItemInfo>, St
|
||||||
let mut show_ascii_dump = false;
|
let mut show_ascii_dump = false;
|
||||||
if is_format_size_char(ch, type_cat, &mut byte_size) {
|
if is_format_size_char(ch, type_cat, &mut byte_size) {
|
||||||
ch = chars.next();
|
ch = chars.next();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
let mut decimal_size = String::new();
|
let mut decimal_size = String::new();
|
||||||
while is_format_size_decimal(ch, type_cat, &mut decimal_size) {
|
while is_format_size_decimal(ch, type_cat, &mut decimal_size) {
|
||||||
ch = chars.next();
|
ch = chars.next();
|
||||||
}
|
}
|
||||||
if !decimal_size.is_empty() {
|
if !decimal_size.is_empty() {
|
||||||
byte_size=match decimal_size.parse() {
|
byte_size = match decimal_size.parse() {
|
||||||
Err(_) => return Err(format!("invalid number '{}' in format specification '{}'", decimal_size, params)),
|
Err(_) => return Err(format!("invalid number '{}' in format specification '{}'", decimal_size, params)),
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ pub enum CommandLineInputs {
|
||||||
/// '-' is used as filename if stdin is meant. This is also returned if
|
/// '-' is used as filename if stdin is meant. This is also returned if
|
||||||
/// there is no input, as stdin is the default input.
|
/// there is no input, as stdin is the default input.
|
||||||
pub fn parse_inputs(matches: &CommandLineOpts) -> Result<CommandLineInputs, String> {
|
pub fn parse_inputs(matches: &CommandLineOpts) -> Result<CommandLineInputs, String> {
|
||||||
|
|
||||||
let mut input_strings: Vec<String> = matches.inputs();
|
let mut input_strings: Vec<String> = matches.inputs();
|
||||||
|
|
||||||
if matches.opts_present(&["traditional"]) {
|
if matches.opts_present(&["traditional"]) {
|
||||||
|
@ -53,7 +52,7 @@ pub fn parse_inputs(matches: &CommandLineOpts) -> Result<CommandLineInputs, Stri
|
||||||
// if any of the options -A, -j, -N, -t, -v or -w are present there is no offset
|
// if any of the options -A, -j, -N, -t, -v or -w are present there is no offset
|
||||||
if !matches.opts_present(&["A", "j", "N", "t", "v", "w"]) {
|
if !matches.opts_present(&["A", "j", "N", "t", "v", "w"]) {
|
||||||
// test if the last input can be parsed as an offset.
|
// test if the last input can be parsed as an offset.
|
||||||
let offset=parse_offset_operand(&input_strings[input_strings.len()-1]);
|
let offset = parse_offset_operand(&input_strings[input_strings.len()-1]);
|
||||||
match offset {
|
match offset {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
// if there is just 1 input (stdin), an offset must start with '+'
|
// if there is just 1 input (stdin), an offset must start with '+'
|
||||||
|
@ -80,22 +79,22 @@ pub fn parse_inputs(matches: &CommandLineOpts) -> Result<CommandLineInputs, Stri
|
||||||
/// interprets inputs when --traditional is on the commandline
|
/// interprets inputs when --traditional is on the commandline
|
||||||
///
|
///
|
||||||
/// normally returns CommandLineInputs::FileAndOffset, but if no offset is found,
|
/// normally returns CommandLineInputs::FileAndOffset, but if no offset is found,
|
||||||
/// it returns CommandLineInputs::FileNames (also to differentiate from the offset==0)
|
/// it returns CommandLineInputs::FileNames (also to differentiate from the offset == 0)
|
||||||
pub fn parse_inputs_traditional(input_strings: Vec<String>) -> Result<CommandLineInputs, String> {
|
pub fn parse_inputs_traditional(input_strings: Vec<String>) -> Result<CommandLineInputs, String> {
|
||||||
match input_strings.len() {
|
match input_strings.len() {
|
||||||
0 => {
|
0 => {
|
||||||
Ok(CommandLineInputs::FileNames(vec!{"-".to_string()}))
|
Ok(CommandLineInputs::FileNames(vec!["-".to_string()]))
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let offset0=parse_offset_operand(&input_strings[0]);
|
let offset0 = parse_offset_operand(&input_strings[0]);
|
||||||
Ok(match offset0 {
|
Ok(match offset0 {
|
||||||
Ok(n) => CommandLineInputs::FileAndOffset(("-".to_string(), n, None)),
|
Ok(n) => CommandLineInputs::FileAndOffset(("-".to_string(), n, None)),
|
||||||
_ => CommandLineInputs::FileNames(input_strings),
|
_ => CommandLineInputs::FileNames(input_strings),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let offset0=parse_offset_operand(&input_strings[0]);
|
let offset0 = parse_offset_operand(&input_strings[0]);
|
||||||
let offset1=parse_offset_operand(&input_strings[1]);
|
let offset1 = parse_offset_operand(&input_strings[1]);
|
||||||
match (offset0, offset1) {
|
match (offset0, offset1) {
|
||||||
(Ok(n), Ok(m)) => Ok(CommandLineInputs::FileAndOffset(("-".to_string(), n, Some(m)))),
|
(Ok(n), Ok(m)) => Ok(CommandLineInputs::FileAndOffset(("-".to_string(), n, Some(m)))),
|
||||||
(_, Ok(m)) => Ok(CommandLineInputs::FileAndOffset((input_strings[0].clone(), m, None))),
|
(_, Ok(m)) => Ok(CommandLineInputs::FileAndOffset((input_strings[0].clone(), m, None))),
|
||||||
|
@ -103,8 +102,8 @@ pub fn parse_inputs_traditional(input_strings: Vec<String>) -> Result<CommandLin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
let offset=parse_offset_operand(&input_strings[1]);
|
let offset = parse_offset_operand(&input_strings[1]);
|
||||||
let label=parse_offset_operand(&input_strings[2]);
|
let label = parse_offset_operand(&input_strings[2]);
|
||||||
match (offset, label) {
|
match (offset, label) {
|
||||||
(Ok(n), Ok(m)) => Ok(CommandLineInputs::FileAndOffset((input_strings[0].clone(), n, Some(m)))),
|
(Ok(n), Ok(m)) => Ok(CommandLineInputs::FileAndOffset((input_strings[0].clone(), n, Some(m)))),
|
||||||
(Err(_), _) => Err(format!("invalid offset: {}", input_strings[1])),
|
(Err(_), _) => Err(format!("invalid offset: {}", input_strings[1])),
|
||||||
|
@ -131,8 +130,7 @@ pub fn parse_offset_operand(s: &String) -> Result<usize, &'static str> {
|
||||||
if s[start..len].starts_with("0x") || s[start..len].starts_with("0X") {
|
if s[start..len].starts_with("0x") || s[start..len].starts_with("0X") {
|
||||||
start += 2;
|
start += 2;
|
||||||
radix = 16;
|
radix = 16;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if s[start..len].ends_with("b") {
|
if s[start..len].ends_with("b") {
|
||||||
len -= 1;
|
len -= 1;
|
||||||
multiply = 512;
|
multiply = 512;
|
||||||
|
@ -178,7 +176,7 @@ mod tests {
|
||||||
fn opts_present(&self, opts: &[&str]) -> bool {
|
fn opts_present(&self, opts: &[&str]) -> bool {
|
||||||
for expected in opts.iter() {
|
for expected in opts.iter() {
|
||||||
for actual in self.option_names.iter() {
|
for actual in self.option_names.iter() {
|
||||||
if *expected==*actual {
|
if *expected == *actual {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,31 +187,30 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_inputs_normal() {
|
fn test_parse_inputs_normal() {
|
||||||
|
assert_eq!(CommandLineInputs::FileNames(vec!["-".to_string()]),
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"-".to_string()}),
|
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{},
|
vec![],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"-".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["-".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"-"},
|
vec!["-"],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"file1".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["file1".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1"},
|
vec!["file1"],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"file1".to_string(), "file2".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["file1".to_string(), "file2".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1", "file2"},
|
vec!["file1", "file2"],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"-".to_string(), "file1".to_string(), "file2".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["-".to_string(), "file1".to_string(), "file2".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"-", "file1", "file2"},
|
vec!["-", "file1", "file2"],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -221,113 +218,112 @@ mod tests {
|
||||||
// offset is found without filename, so stdin will be used.
|
// offset is found without filename, so stdin will be used.
|
||||||
assert_eq!(CommandLineInputs::FileAndOffset(("-".to_string(), 8, None)),
|
assert_eq!(CommandLineInputs::FileAndOffset(("-".to_string(), 8, None)),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"+10"},
|
vec!["+10"],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
|
|
||||||
// offset must start with "+" if no input is specified.
|
// offset must start with "+" if no input is specified.
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"10".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["10".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"10"},
|
vec!["10"],
|
||||||
vec!{""})).unwrap());
|
vec![""])).unwrap());
|
||||||
|
|
||||||
// offset is not valid, so it is considered a filename.
|
// offset is not valid, so it is considered a filename.
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"+10a".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["+10a".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"+10a"},
|
vec!["+10a"],
|
||||||
vec!{""})).unwrap());
|
vec![""])).unwrap());
|
||||||
|
|
||||||
// if -j is included in the commandline, there cannot be an offset.
|
// if -j is included in the commandline, there cannot be an offset.
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"+10".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["+10".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"+10"},
|
vec!["+10"],
|
||||||
vec!{"j"})).unwrap());
|
vec!["j"])).unwrap());
|
||||||
|
|
||||||
// if -v is included in the commandline, there cannot be an offset.
|
// if -v is included in the commandline, there cannot be an offset.
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"+10".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["+10".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"+10"},
|
vec!["+10"],
|
||||||
vec!{"o", "v"})).unwrap());
|
vec!["o", "v"])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, None)),
|
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, None)),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1", "+10"},
|
vec!["file1", "+10"],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
|
|
||||||
// offset does not need to start with "+" if a filename is included.
|
// offset does not need to start with "+" if a filename is included.
|
||||||
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, None)),
|
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, None)),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1", "10"},
|
vec!["file1", "10"],
|
||||||
vec!{})).unwrap());
|
vec![])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"file1".to_string(), "+10a".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["file1".to_string(), "+10a".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1", "+10a"},
|
vec!["file1", "+10a"],
|
||||||
vec!{""})).unwrap());
|
vec![""])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"file1".to_string(), "+10".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["file1".to_string(), "+10".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1", "+10"},
|
vec!["file1", "+10"],
|
||||||
vec!{"j"})).unwrap());
|
vec!["j"])).unwrap());
|
||||||
|
|
||||||
// offset must be last on the commandline
|
// offset must be last on the commandline
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"+10".to_string(), "file1".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["+10".to_string(), "file1".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"+10", "file1"},
|
vec!["+10", "file1"],
|
||||||
vec!{""})).unwrap());
|
vec![""])).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_inputs_traditional() {
|
fn test_parse_inputs_traditional() {
|
||||||
|
|
||||||
// it should not return FileAndOffset to signal no offset was entered on the commandline.
|
// it should not return FileAndOffset to signal no offset was entered on the commandline.
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"-".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["-".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{},
|
vec![],
|
||||||
vec!{"traditional"})).unwrap());
|
vec!["traditional"])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileNames(vec!{"file1".to_string()}),
|
assert_eq!(CommandLineInputs::FileNames(vec!["file1".to_string()]),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1"},
|
vec!["file1"],
|
||||||
vec!{"traditional"})).unwrap());
|
vec!["traditional"])).unwrap());
|
||||||
|
|
||||||
// offset does not need to start with a +
|
// offset does not need to start with a +
|
||||||
assert_eq!(CommandLineInputs::FileAndOffset(("-".to_string(), 8, None)),
|
assert_eq!(CommandLineInputs::FileAndOffset(("-".to_string(), 8, None)),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"10"},
|
vec!["10"],
|
||||||
vec!{"traditional"})).unwrap());
|
vec!["traditional"])).unwrap());
|
||||||
|
|
||||||
// valid offset and valid label
|
// valid offset and valid label
|
||||||
assert_eq!(CommandLineInputs::FileAndOffset(("-".to_string(), 8, Some(8))),
|
assert_eq!(CommandLineInputs::FileAndOffset(("-".to_string(), 8, Some(8))),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"10", "10"},
|
vec!["10", "10"],
|
||||||
vec!{"traditional"})).unwrap());
|
vec!["traditional"])).unwrap());
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, None)),
|
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, None)),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1", "10"},
|
vec!["file1", "10"],
|
||||||
vec!{"traditional"})).unwrap());
|
vec!["traditional"])).unwrap());
|
||||||
|
|
||||||
// only one file is allowed, it must be the first
|
// only one file is allowed, it must be the first
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"10", "file1"},
|
vec!["10", "file1"],
|
||||||
vec!{"traditional"})).unwrap_err();
|
vec!["traditional"])).unwrap_err();
|
||||||
|
|
||||||
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, Some(8))),
|
assert_eq!(CommandLineInputs::FileAndOffset(("file1".to_string(), 8, Some(8))),
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"file1", "10", "10"},
|
vec!["file1", "10", "10"],
|
||||||
vec!{"traditional"})).unwrap());
|
vec!["traditional"])).unwrap());
|
||||||
|
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"10", "file1", "10"},
|
vec!["10", "file1", "10"],
|
||||||
vec!{"traditional"})).unwrap_err();
|
vec!["traditional"])).unwrap_err();
|
||||||
|
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"10", "10", "file1"},
|
vec!["10", "10", "file1"],
|
||||||
vec!{"traditional"})).unwrap_err();
|
vec!["traditional"])).unwrap_err();
|
||||||
|
|
||||||
parse_inputs(&MockOptions::new(
|
parse_inputs(&MockOptions::new(
|
||||||
vec!{"10", "10", "10", "10"},
|
vec!["10", "10", "10", "10"],
|
||||||
vec!{"traditional"})).unwrap_err();
|
vec!["traditional"])).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_offset_operand_str(s: &str) -> Result<usize, &'static str> {
|
fn parse_offset_operand_str(s: &str) -> Result<usize, &'static str> {
|
||||||
|
@ -363,5 +359,4 @@ mod tests {
|
||||||
assert_eq!(5120, parse_offset_operand_str("+10.b").unwrap()); // b suffix = *512
|
assert_eq!(5120, parse_offset_operand_str("+10.b").unwrap()); // b suffix = *512
|
||||||
assert_eq!(267, parse_offset_operand_str("0x10b").unwrap()); // hex
|
assert_eq!(267, parse_offset_operand_str("0x10b").unwrap()); // hex
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ pub fn parse_number_of_bytes(s: &String) -> Result<usize, &'static str> {
|
||||||
if s.starts_with("0x") || s.starts_with("0X") {
|
if s.starts_with("0x") || s.starts_with("0X") {
|
||||||
start = 2;
|
start = 2;
|
||||||
radix = 16;
|
radix = 16;
|
||||||
}
|
} else if s.starts_with("0") {
|
||||||
else if s.starts_with("0") {
|
|
||||||
radix = 8;
|
radix = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,40 +23,40 @@ pub fn parse_number_of_bytes(s: &String) -> Result<usize, &'static str> {
|
||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
Some('m') | Some('M') => {
|
Some('m') | Some('M') => {
|
||||||
multiply = 1024*1024;
|
multiply = 1024 * 1024;
|
||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
Some('G') => {
|
Some('G') => {
|
||||||
multiply = 1024*1024*1024;
|
multiply = 1024 * 1024 * 1024;
|
||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
Some('T') => {
|
Some('T') => {
|
||||||
multiply = 1024*1024*1024*1024;
|
multiply = 1024 * 1024 * 1024 * 1024;
|
||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
Some('P') => {
|
Some('P') => {
|
||||||
multiply = 1024*1024*1024*1024*1024;
|
multiply = 1024 * 1024 * 1024 * 1024 * 1024;
|
||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
Some('E') => {
|
Some('E') => {
|
||||||
multiply = 1024*1024*1024*1024*1024*1024;
|
multiply = 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
|
||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
Some('B') if radix != 16 => {
|
Some('B') if radix != 16 => {
|
||||||
len -= 2;
|
len -= 2;
|
||||||
multiply = match ends_with.next() {
|
multiply = match ends_with.next() {
|
||||||
Some('k') | Some('K') => 1000,
|
Some('k') | Some('K') => 1000,
|
||||||
Some('m') | Some('M') => 1000*1000,
|
Some('m') | Some('M') => 1000 * 1000,
|
||||||
Some('G') => 1000*1000*1000,
|
Some('G') => 1000 * 1000 * 1000,
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
Some('T') => 1000*1000*1000*1000,
|
Some('T') => 1000 * 1000 * 1000 * 1000,
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
Some('P') => 1000*1000*1000*1000*1000,
|
Some('P') => 1000 * 1000 * 1000 * 1000 * 1000,
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
Some('E') => 1000*1000*1000*1000*1000*1000,
|
Some('E') => 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
|
||||||
_ => return Err("parse failed"),
|
_ => return Err("parse failed"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -81,11 +80,11 @@ fn test_parse_number_of_bytes() {
|
||||||
assert_eq!(0, parse_number_of_bytes_str("0").unwrap());
|
assert_eq!(0, parse_number_of_bytes_str("0").unwrap());
|
||||||
assert_eq!(5, parse_number_of_bytes_str("5").unwrap());
|
assert_eq!(5, parse_number_of_bytes_str("5").unwrap());
|
||||||
assert_eq!(999, parse_number_of_bytes_str("999").unwrap());
|
assert_eq!(999, parse_number_of_bytes_str("999").unwrap());
|
||||||
assert_eq!(2*512, parse_number_of_bytes_str("2b").unwrap());
|
assert_eq!(2 * 512, parse_number_of_bytes_str("2b").unwrap());
|
||||||
assert_eq!(2*1024, parse_number_of_bytes_str("2k").unwrap());
|
assert_eq!(2 * 1024, parse_number_of_bytes_str("2k").unwrap());
|
||||||
assert_eq!(4*1024, parse_number_of_bytes_str("4K").unwrap());
|
assert_eq!(4 * 1024, parse_number_of_bytes_str("4K").unwrap());
|
||||||
assert_eq!(2*1048576, parse_number_of_bytes_str("2m").unwrap());
|
assert_eq!(2 * 1048576, parse_number_of_bytes_str("2m").unwrap());
|
||||||
assert_eq!(4*1048576, parse_number_of_bytes_str("4M").unwrap());
|
assert_eq!(4 * 1048576, parse_number_of_bytes_str("4M").unwrap());
|
||||||
assert_eq!(1073741824, parse_number_of_bytes_str("1G").unwrap());
|
assert_eq!(1073741824, parse_number_of_bytes_str("1G").unwrap());
|
||||||
assert_eq!(2000, parse_number_of_bytes_str("2kB").unwrap());
|
assert_eq!(2000, parse_number_of_bytes_str("2kB").unwrap());
|
||||||
assert_eq!(4000, parse_number_of_bytes_str("4KB").unwrap());
|
assert_eq!(4000, parse_number_of_bytes_str("4KB").unwrap());
|
||||||
|
@ -95,16 +94,16 @@ fn test_parse_number_of_bytes() {
|
||||||
|
|
||||||
// octal input
|
// octal input
|
||||||
assert_eq!(8, parse_number_of_bytes_str("010").unwrap());
|
assert_eq!(8, parse_number_of_bytes_str("010").unwrap());
|
||||||
assert_eq!(8*512, parse_number_of_bytes_str("010b").unwrap());
|
assert_eq!(8 * 512, parse_number_of_bytes_str("010b").unwrap());
|
||||||
assert_eq!(8*1024, parse_number_of_bytes_str("010k").unwrap());
|
assert_eq!(8 * 1024, parse_number_of_bytes_str("010k").unwrap());
|
||||||
assert_eq!(8*1048576, parse_number_of_bytes_str("010m").unwrap());
|
assert_eq!(8 * 1048576, parse_number_of_bytes_str("010m").unwrap());
|
||||||
|
|
||||||
// hex input
|
// hex input
|
||||||
assert_eq!(15, parse_number_of_bytes_str("0xf").unwrap());
|
assert_eq!(15, parse_number_of_bytes_str("0xf").unwrap());
|
||||||
assert_eq!(15, parse_number_of_bytes_str("0XF").unwrap());
|
assert_eq!(15, parse_number_of_bytes_str("0XF").unwrap());
|
||||||
assert_eq!(27, parse_number_of_bytes_str("0x1b").unwrap());
|
assert_eq!(27, parse_number_of_bytes_str("0x1b").unwrap());
|
||||||
assert_eq!(16*1024, parse_number_of_bytes_str("0x10k").unwrap());
|
assert_eq!(16 * 1024, parse_number_of_bytes_str("0x10k").unwrap());
|
||||||
assert_eq!(16*1048576, parse_number_of_bytes_str("0x10m").unwrap());
|
assert_eq!(16 * 1048576, parse_number_of_bytes_str("0x10m").unwrap());
|
||||||
|
|
||||||
// invalid input
|
// invalid input
|
||||||
parse_number_of_bytes_str("").unwrap_err();
|
parse_number_of_bytes_str("").unwrap_err();
|
||||||
|
|
|
@ -5,7 +5,7 @@ use multifilereader::HasError;
|
||||||
|
|
||||||
/// When a large number of bytes must be skipped, it will be read into a
|
/// When a large number of bytes must be skipped, it will be read into a
|
||||||
/// dynamically allocated buffer. The buffer will be limited to this size.
|
/// dynamically allocated buffer. The buffer will be limited to this size.
|
||||||
const MAX_SKIP_BUFFER: usize = 64*1024;
|
const MAX_SKIP_BUFFER: usize = 64 * 1024;
|
||||||
|
|
||||||
/// Wrapper for `std::io::Read` which can skip bytes at the beginning
|
/// Wrapper for `std::io::Read` which can skip bytes at the beginning
|
||||||
/// of the input, and it can limit the returned bytes to a particular
|
/// of the input, and it can limit the returned bytes to a particular
|
||||||
|
|
|
@ -91,8 +91,7 @@ impl<R: Read> PeekRead for PeekReader<R> {
|
||||||
let unused = out.len() - bytes_in_buffer;
|
let unused = out.len() - bytes_in_buffer;
|
||||||
if peek_size <= unused {
|
if peek_size <= unused {
|
||||||
Ok((bytes_in_buffer, 0))
|
Ok((bytes_in_buffer, 0))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
let actual_peek_size = peek_size - unused;
|
let actual_peek_size = peek_size - unused;
|
||||||
let real_size = bytes_in_buffer - actual_peek_size;
|
let real_size = bytes_in_buffer - actual_peek_size;
|
||||||
self.write_to_tempbuffer(&out[real_size..bytes_in_buffer]);
|
self.write_to_tempbuffer(&out[real_size..bytes_in_buffer]);
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub static FORMAT_ITEM_C: FormatterItemInfo = FormatterItemInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static A_CHRS : [&'static str; 128] =
|
static A_CHRS: [&'static str; 128] =
|
||||||
["nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
|
["nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
|
||||||
"bs", "ht", "nl", "vt", "ff", "cr", "so", "si",
|
"bs", "ht", "nl", "vt", "ff", "cr", "so", "si",
|
||||||
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
|
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
|
||||||
|
@ -40,7 +40,7 @@ fn format_item_a(p: u64) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static C_CHRS : [&'static str; 128] = [
|
static C_CHRS: [&'static str; 128] = [
|
||||||
"\\0", "001", "002", "003", "004", "005", "006", "\\a",
|
"\\0", "001", "002", "003", "004", "005", "006", "\\a",
|
||||||
"\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "016", "017",
|
"\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "016", "017",
|
||||||
"020", "021", "022", "023", "024", "025", "026", "027",
|
"020", "021", "022", "023", "024", "025", "026", "027",
|
||||||
|
@ -68,33 +68,28 @@ fn format_item_c(bytes: &[u8]) -> String {
|
||||||
Some(s) => format!("{:>4}", s),
|
Some(s) => format!("{:>4}", s),
|
||||||
None => format!("{:>4}", b),
|
None => format!("{:>4}", b),
|
||||||
}
|
}
|
||||||
}
|
} else if (b & 0xc0) == 0x80 {
|
||||||
else if (b & 0xc0) == 0x80 {
|
|
||||||
// second or subsequent octet of an utf-8 sequence
|
// second or subsequent octet of an utf-8 sequence
|
||||||
String::from(" **")
|
String::from(" **")
|
||||||
}
|
} else if ((b & 0xe0) == 0xc0) && (bytes.len() >= 2) {
|
||||||
else if ((b & 0xe0) == 0xc0) && (bytes.len() >= 2) {
|
|
||||||
// start of a 2 octet utf-8 sequence
|
// start of a 2 octet utf-8 sequence
|
||||||
match from_utf8(&bytes[0..2]) {
|
match from_utf8(&bytes[0..2]) {
|
||||||
Ok(s) => { format!("{:>4}", s) },
|
Ok(s) => { format!("{:>4}", s) },
|
||||||
Err(_) => { format!(" {:03o}", b) },
|
Err(_) => { format!(" {:03o}", b) },
|
||||||
}
|
}
|
||||||
}
|
} else if ((b & 0xf0) == 0xe0) && (bytes.len() >= 3) {
|
||||||
else if ((b & 0xf0) == 0xe0) && (bytes.len() >= 3) {
|
|
||||||
// start of a 3 octet utf-8 sequence
|
// start of a 3 octet utf-8 sequence
|
||||||
match from_utf8(&bytes[0..3]) {
|
match from_utf8(&bytes[0..3]) {
|
||||||
Ok(s) => { format!("{:>4}", s) },
|
Ok(s) => { format!("{:>4}", s) },
|
||||||
Err(_) => { format!(" {:03o}", b) },
|
Err(_) => { format!(" {:03o}", b) },
|
||||||
}
|
}
|
||||||
}
|
} else if ((b & 0xf8) == 0xf0) && (bytes.len() >= 4) {
|
||||||
else if ((b & 0xf8) == 0xf0) && (bytes.len() >= 4) {
|
|
||||||
// start of a 4 octet utf-8 sequence
|
// start of a 4 octet utf-8 sequence
|
||||||
match from_utf8(&bytes[0..4]) {
|
match from_utf8(&bytes[0..4]) {
|
||||||
Ok(s) => { format!("{:>4}", s) },
|
Ok(s) => { format!("{:>4}", s) },
|
||||||
Err(_) => { format!(" {:03o}", b) },
|
Err(_) => { format!(" {:03o}", b) },
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// invalid utf-8
|
// invalid utf-8
|
||||||
format!(" {:03o}", b)
|
format!(" {:03o}", b)
|
||||||
}
|
}
|
||||||
|
@ -107,8 +102,7 @@ pub fn format_ascii_dump(bytes: &[u8]) -> String {
|
||||||
for c in bytes.iter() {
|
for c in bytes.iter() {
|
||||||
if *c >= 0x20 && *c <= 0x7e {
|
if *c >= 0x20 && *c <= 0x7e {
|
||||||
result.push_str(C_CHRS[*c as usize]);
|
result.push_str(C_CHRS[*c as usize]);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
result.push('.');
|
result.push('.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,7 @@ fn format_flo32(f: f32) -> String {
|
||||||
if f.classify() == FpCategory::Subnormal {
|
if f.classify() == FpCategory::Subnormal {
|
||||||
// subnormal numbers will be normal as f64, so will print with a wrong precision
|
// subnormal numbers will be normal as f64, so will print with a wrong precision
|
||||||
format!("{:width$e}", f, width = width) // subnormal numbers
|
format!("{:width$e}", f, width = width) // subnormal numbers
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
format_float(f as f64, width, precision)
|
format_float(f as f64, width, precision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +57,6 @@ fn format_flo64(f: f64) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_float(f: f64, width: usize, precision: usize) -> String {
|
fn format_float(f: f64, width: usize, precision: usize) -> String {
|
||||||
|
|
||||||
if !f.is_normal() {
|
if !f.is_normal() {
|
||||||
if f == -0.0 && f.is_sign_negative() { return format!("{:>width$}", "-0", width = width) }
|
if f == -0.0 && f.is_sign_negative() { return format!("{:>width$}", "-0", width = width) }
|
||||||
if f == 0.0 || !f.is_finite() { return format!("{:width$}", f, width = width) }
|
if f == 0.0 || !f.is_finite() { return format!("{:width$}", f, width = width) }
|
||||||
|
@ -77,13 +75,11 @@ fn format_float(f: f64, width: usize, precision: usize) -> String {
|
||||||
format!("{:width$.dec$}", f,
|
format!("{:width$.dec$}", f,
|
||||||
width = width,
|
width = width,
|
||||||
dec = (precision-1) - l as usize)
|
dec = (precision-1) - l as usize)
|
||||||
}
|
} else if l == -1 {
|
||||||
else if l == -1 {
|
|
||||||
format!("{:width$.dec$}", f,
|
format!("{:width$.dec$}", f,
|
||||||
width = width,
|
width = width,
|
||||||
dec = precision)
|
dec = precision)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
format!("{:width$.dec$e}", f,
|
format!("{:width$.dec$e}", f,
|
||||||
width = width,
|
width = width,
|
||||||
dec = precision - 1)
|
dec = precision - 1)
|
||||||
|
|
|
@ -89,20 +89,17 @@ fn test_no_file() {
|
||||||
// Test that od reads from stdin instead of a file
|
// Test that od reads from stdin instead of a file
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_stdin() {
|
fn test_from_stdin() {
|
||||||
|
|
||||||
let input = "abcdefghijklmnopqrstuvwxyz\n";
|
let input = "abcdefghijklmnopqrstuvwxyz\n";
|
||||||
let result = new_ucmd!().arg("--endian=little").run_piped_stdin(input.as_bytes());
|
let result = new_ucmd!().arg("--endian=little").run_piped_stdin(input.as_bytes());
|
||||||
|
|
||||||
assert_empty_stderr!(result);
|
assert_empty_stderr!(result);
|
||||||
assert!(result.success);
|
assert!(result.success);
|
||||||
assert_eq!(result.stdout, unindent(ALPHA_OUT));
|
assert_eq!(result.stdout, unindent(ALPHA_OUT));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that od reads from stdin and also from files
|
// Test that od reads from stdin and also from files
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_mixed() {
|
fn test_from_mixed() {
|
||||||
|
|
||||||
let temp = env::temp_dir();
|
let temp = env::temp_dir();
|
||||||
let tmpdir = Path::new(&temp);
|
let tmpdir = Path::new(&temp);
|
||||||
let file1 = tmpdir.join("test-1");
|
let file1 = tmpdir.join("test-1");
|
||||||
|
@ -122,12 +119,10 @@ fn test_from_mixed() {
|
||||||
assert_empty_stderr!(result);
|
assert_empty_stderr!(result);
|
||||||
assert!(result.success);
|
assert!(result.success);
|
||||||
assert_eq!(result.stdout, unindent(ALPHA_OUT));
|
assert_eq!(result.stdout, unindent(ALPHA_OUT));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multiple_formats() {
|
fn test_multiple_formats() {
|
||||||
|
|
||||||
let input = "abcdefghijklmnopqrstuvwxyz\n";
|
let input = "abcdefghijklmnopqrstuvwxyz\n";
|
||||||
let result = new_ucmd!().arg("-c").arg("-b").run_piped_stdin(input.as_bytes());
|
let result = new_ucmd!().arg("-c").arg("-b").run_piped_stdin(input.as_bytes());
|
||||||
|
|
||||||
|
@ -140,12 +135,10 @@ fn test_multiple_formats() {
|
||||||
161 162 163 164 165 166 167 170 171 172 012
|
161 162 163 164 165 166 167 170 171 172 012
|
||||||
0000033
|
0000033
|
||||||
"));
|
"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dec() {
|
fn test_dec() {
|
||||||
|
|
||||||
let input = [
|
let input = [
|
||||||
0u8, 0u8,
|
0u8, 0u8,
|
||||||
1u8, 0u8,
|
1u8, 0u8,
|
||||||
|
@ -163,13 +156,11 @@ fn test_dec() {
|
||||||
assert_empty_stderr!(result);
|
assert_empty_stderr!(result);
|
||||||
assert!(result.success);
|
assert!(result.success);
|
||||||
assert_eq!(result.stdout, expected_output);
|
assert_eq!(result.stdout, expected_output);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hex16(){
|
fn test_hex16(){
|
||||||
|
let input: [u8; 9] = [
|
||||||
let input : [u8; 9] = [
|
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xff];
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xff];
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 2301 6745 ab89 efcd 00ff
|
0000000 2301 6745 ab89 efcd 00ff
|
||||||
|
@ -184,8 +175,7 @@ fn test_hex16(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hex32(){
|
fn test_hex32(){
|
||||||
|
let input: [u8; 9] = [
|
||||||
let input : [u8; 9] = [
|
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xff];
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xff];
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 67452301 efcdab89 000000ff
|
0000000 67452301 efcdab89 000000ff
|
||||||
|
@ -200,8 +190,7 @@ fn test_hex32(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_f16(){
|
fn test_f16(){
|
||||||
|
let input: [u8; 14] = [
|
||||||
let input : [u8; 14] = [
|
|
||||||
0x00, 0x3c, // 0x3C00 1.0
|
0x00, 0x3c, // 0x3C00 1.0
|
||||||
0x00, 0x00, // 0x0000 0.0
|
0x00, 0x00, // 0x0000 0.0
|
||||||
0x00, 0x80, // 0x8000 -0.0
|
0x00, 0x80, // 0x8000 -0.0
|
||||||
|
@ -223,8 +212,7 @@ fn test_f16(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_f32(){
|
fn test_f32(){
|
||||||
|
let input: [u8; 28] = [
|
||||||
let input : [u8; 28] = [
|
|
||||||
0x52, 0x06, 0x9e, 0xbf, // 0xbf9e0652 -1.2345679
|
0x52, 0x06, 0x9e, 0xbf, // 0xbf9e0652 -1.2345679
|
||||||
0x4e, 0x61, 0x3c, 0x4b, // 0x4b3c614e 12345678
|
0x4e, 0x61, 0x3c, 0x4b, // 0x4b3c614e 12345678
|
||||||
0x0f, 0x9b, 0x94, 0xfe, // 0xfe949b0f -9.876543E37
|
0x0f, 0x9b, 0x94, 0xfe, // 0xfe949b0f -9.876543E37
|
||||||
|
@ -246,8 +234,7 @@ fn test_f32(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_f64(){
|
fn test_f64(){
|
||||||
|
let input: [u8; 40] = [
|
||||||
let input : [u8; 40] = [
|
|
||||||
0x27, 0x6b, 0x0a, 0x2f, 0x2a, 0xee, 0x45, 0x43, // 0x4345EE2A2F0A6B27 12345678912345678
|
0x27, 0x6b, 0x0a, 0x2f, 0x2a, 0xee, 0x45, 0x43, // 0x4345EE2A2F0A6B27 12345678912345678
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0000000000000000 0
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0000000000000000 0
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, // 0x8010000000000000 -2.2250738585072014e-308
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, // 0x8010000000000000 -2.2250738585072014e-308
|
||||||
|
@ -268,7 +255,6 @@ fn test_f64(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multibyte() {
|
fn test_multibyte() {
|
||||||
|
|
||||||
let result = new_ucmd!().arg("-c").arg("-w12").run_piped_stdin("Universität Tübingen \u{1B000}".as_bytes());
|
let result = new_ucmd!().arg("-c").arg("-w12").run_piped_stdin("Universität Tübingen \u{1B000}".as_bytes());
|
||||||
|
|
||||||
assert_empty_stderr!(result);
|
assert_empty_stderr!(result);
|
||||||
|
@ -283,8 +269,7 @@ fn test_multibyte() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_width(){
|
fn test_width(){
|
||||||
|
let input: [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
|
||||||
let input : [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
|
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 000000 000000
|
0000000 000000 000000
|
||||||
0000004 000000 000000
|
0000004 000000 000000
|
||||||
|
@ -300,8 +285,7 @@ fn test_width(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_width(){
|
fn test_invalid_width(){
|
||||||
|
let input: [u8; 4] = [0x00, 0x00, 0x00, 0x00];
|
||||||
let input : [u8; 4] = [0x00, 0x00, 0x00, 0x00];
|
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 000000
|
0000000 000000
|
||||||
0000002 000000
|
0000002 000000
|
||||||
|
@ -317,8 +301,7 @@ fn test_invalid_width(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zero_width(){
|
fn test_zero_width(){
|
||||||
|
let input: [u8; 4] = [0x00, 0x00, 0x00, 0x00];
|
||||||
let input : [u8; 4] = [0x00, 0x00, 0x00, 0x00];
|
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 000000
|
0000000 000000
|
||||||
0000002 000000
|
0000002 000000
|
||||||
|
@ -334,8 +317,7 @@ fn test_zero_width(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_width_without_value(){
|
fn test_width_without_value(){
|
||||||
|
let input: [u8; 40] = [0 ; 40];
|
||||||
let input : [u8; 40] = [0 ; 40];
|
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
|
0000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
|
||||||
0000040 000000 000000 000000 000000
|
0000040 000000 000000 000000 000000
|
||||||
|
@ -351,7 +333,6 @@ fn test_width_without_value(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_suppress_duplicates(){
|
fn test_suppress_duplicates(){
|
||||||
|
|
||||||
let input: [u8; 41] = [
|
let input: [u8; 41] = [
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
|
@ -387,8 +368,7 @@ fn test_suppress_duplicates(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_big_endian() {
|
fn test_big_endian() {
|
||||||
|
let input: [u8; 8] = [
|
||||||
let input : [u8; 8] = [
|
|
||||||
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];// 0xc000000000000000 -2
|
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];// 0xc000000000000000 -2
|
||||||
|
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
|
@ -409,8 +389,7 @@ fn test_big_endian() {
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn test_alignment_Xxa() {
|
fn test_alignment_Xxa() {
|
||||||
|
let input: [u8; 8] = [
|
||||||
let input : [u8; 8] = [
|
|
||||||
0x0A, 0x0D, 0x65, 0x66, 0x67, 0x00, 0x9e, 0x9f];
|
0x0A, 0x0D, 0x65, 0x66, 0x67, 0x00, 0x9e, 0x9f];
|
||||||
|
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
|
@ -431,8 +410,7 @@ fn test_alignment_Xxa() {
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn test_alignment_Fx() {
|
fn test_alignment_Fx() {
|
||||||
|
let input: [u8; 8] = [
|
||||||
let input : [u8; 8] = [
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0];// 0xc000000000000000 -2
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0];// 0xc000000000000000 -2
|
||||||
|
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
|
@ -451,7 +429,6 @@ fn test_alignment_Fx() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_maxuint(){
|
fn test_maxuint(){
|
||||||
|
|
||||||
let input = [0xFFu8 ; 8];
|
let input = [0xFFu8 ; 8];
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 1777777777777777777777
|
0000000 1777777777777777777777
|
||||||
|
@ -474,7 +451,6 @@ fn test_maxuint(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hex_offset(){
|
fn test_hex_offset(){
|
||||||
|
|
||||||
let input = [0u8 ; 0x1F];
|
let input = [0u8 ; 0x1F];
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
000000 00000000 00000000 00000000 00000000
|
000000 00000000 00000000 00000000 00000000
|
||||||
|
@ -493,7 +469,6 @@ fn test_hex_offset(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dec_offset(){
|
fn test_dec_offset(){
|
||||||
|
|
||||||
let input = [0u8 ; 19];
|
let input = [0u8 ; 19];
|
||||||
let expected_output = unindent("
|
let expected_output = unindent("
|
||||||
0000000 00000000 00000000 00000000 00000000
|
0000000 00000000 00000000 00000000 00000000
|
||||||
|
@ -512,7 +487,6 @@ fn test_dec_offset(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_no_offset(){
|
fn test_no_offset(){
|
||||||
|
|
||||||
let input = [0u8 ; 31];
|
let input = [0u8 ; 31];
|
||||||
const LINE: &'static str = " 00000000 00000000 00000000 00000000\n";
|
const LINE: &'static str = " 00000000 00000000 00000000 00000000\n";
|
||||||
let expected_output = [LINE, LINE, LINE, LINE].join("");
|
let expected_output = [LINE, LINE, LINE, LINE].join("");
|
||||||
|
@ -526,17 +500,13 @@ fn test_no_offset(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_offset(){
|
fn test_invalid_offset(){
|
||||||
|
let result = new_ucmd!().arg("-Ab").run();
|
||||||
let input = [0u8 ; 4];
|
|
||||||
|
|
||||||
let result = new_ucmd!().arg("-Ab").run_piped_stdin(&input[..]);
|
|
||||||
|
|
||||||
assert!(!result.success);
|
assert!(!result.success);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_skip_bytes(){
|
fn test_skip_bytes(){
|
||||||
|
|
||||||
let input = "abcdefghijklmnopq";
|
let input = "abcdefghijklmnopq";
|
||||||
let result = new_ucmd!().arg("-c").arg("--skip-bytes=5").run_piped_stdin(input.as_bytes());
|
let result = new_ucmd!().arg("-c").arg("--skip-bytes=5").run_piped_stdin(input.as_bytes());
|
||||||
|
|
||||||
|
@ -550,7 +520,6 @@ fn test_skip_bytes(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_skip_bytes_error(){
|
fn test_skip_bytes_error(){
|
||||||
|
|
||||||
let input = "12345";
|
let input = "12345";
|
||||||
let result = new_ucmd!().arg("--skip-bytes=10").run_piped_stdin(input.as_bytes());
|
let result = new_ucmd!().arg("--skip-bytes=10").run_piped_stdin(input.as_bytes());
|
||||||
|
|
||||||
|
@ -559,7 +528,6 @@ fn test_skip_bytes_error(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_read_bytes(){
|
fn test_read_bytes(){
|
||||||
|
|
||||||
let input = "abcdefghijklmnopqrstuvwxyz\n12345678";
|
let input = "abcdefghijklmnopqrstuvwxyz\n12345678";
|
||||||
let result = new_ucmd!().arg("--endian=little").arg("--read-bytes=27").run_piped_stdin(input.as_bytes());
|
let result = new_ucmd!().arg("--endian=little").arg("--read-bytes=27").run_piped_stdin(input.as_bytes());
|
||||||
|
|
||||||
|
@ -570,8 +538,7 @@ fn test_read_bytes(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ascii_dump(){
|
fn test_ascii_dump(){
|
||||||
|
let input: [u8; 22] = [
|
||||||
let input : [u8; 22] = [
|
|
||||||
0x00, 0x01, 0x0a, 0x0d, 0x10, 0x1f, 0x20, 0x61, 0x62, 0x63, 0x7d,
|
0x00, 0x01, 0x0a, 0x0d, 0x10, 0x1f, 0x20, 0x61, 0x62, 0x63, 0x7d,
|
||||||
0x7e, 0x7f, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff];
|
0x7e, 0x7f, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff];
|
||||||
let result = new_ucmd!().arg("-tx1zacz").run_piped_stdin(&input[..]);
|
let result = new_ucmd!().arg("-tx1zacz").run_piped_stdin(&input[..]);
|
||||||
|
@ -607,7 +574,6 @@ fn test_filename_parsing(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stdin_offset(){
|
fn test_stdin_offset(){
|
||||||
|
|
||||||
let input = "abcdefghijklmnopq";
|
let input = "abcdefghijklmnopq";
|
||||||
let result = new_ucmd!().arg("-c").arg("+5").run_piped_stdin(input.as_bytes());
|
let result = new_ucmd!().arg("-c").arg("+5").run_piped_stdin(input.as_bytes());
|
||||||
|
|
||||||
|
@ -621,7 +587,6 @@ fn test_stdin_offset(){
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_file_offset(){
|
fn test_file_offset(){
|
||||||
|
|
||||||
let result = new_ucmd!().arg("-c").arg("--").arg("-f").arg("10").run();
|
let result = new_ucmd!().arg("-c").arg("--").arg("-f").arg("10").run();
|
||||||
|
|
||||||
assert_empty_stderr!(result);
|
assert_empty_stderr!(result);
|
||||||
|
@ -678,8 +643,7 @@ fn test_traditional_with_skip_bytes_non_override(){
|
||||||
#[test]
|
#[test]
|
||||||
fn test_traditional_error(){
|
fn test_traditional_error(){
|
||||||
// file "0" exists - don't fail on that, but --traditional only accepts a single input
|
// file "0" exists - don't fail on that, but --traditional only accepts a single input
|
||||||
let input = "abcdefghijklmnopq";
|
let result = new_ucmd!().arg("--traditional").arg("0").arg("0").arg("0").arg("0").run();
|
||||||
let result = new_ucmd!().arg("--traditional").arg("0").arg("0").arg("0").arg("0").run_piped_stdin(input.as_bytes());
|
|
||||||
|
|
||||||
assert!(!result.success);
|
assert!(!result.success);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue