diff --git a/Cargo.lock b/Cargo.lock index 32e89bfb9..ebe84879a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -667,6 +667,7 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "unindent 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uucore 0.0.1", ] [[package]] diff --git a/src/od/Cargo.toml b/src/od/Cargo.toml index 555c82875..0b44a8633 100644 --- a/src/od/Cargo.toml +++ b/src/od/Cargo.toml @@ -12,6 +12,7 @@ getopts = "*" libc = "*" unindent = "*" byteorder = "*" +uucore = { path="../uucore" } [[bin]] name = "od" diff --git a/src/od/od.rs b/src/od/od.rs index fdb7b7dcd..f46ed8c64 100644 --- a/src/od/od.rs +++ b/src/od/od.rs @@ -13,12 +13,16 @@ extern crate getopts; extern crate unindent; extern crate byteorder; +#[macro_use] +extern crate uucore; + mod multifilereader; mod prn_int; mod prn_char; mod prn_float; -use std::f64; +use std::cmp; +use std::io::Write; use unindent::*; use byteorder::*; use multifilereader::*; @@ -73,7 +77,7 @@ pub fn uumain(args: Vec) -> i32 { opts.optopt("t", "format", "select output format or formats", "TYPE"); opts.optflag("v", "output-duplicates", "do not use * to mark line suppression"); - opts.optopt("w", "width", + opts.optflagopt("w", "width", ("output BYTES bytes per output line. 32 is implied when BYTES is not \ specified."), "BYTES"); @@ -209,23 +213,36 @@ pub fn uumain(args: Vec) -> i32 { formats.push(mkfmt(2, &oct)); // 2 byte octal is the default } - odfunc(&input_offset_base, &inputs, &formats[..]) + let mut line_bytes = match matches.opt_default("w", "32") { + None => 16, + Some(s) => { + match s.parse::() { + Ok(i) => { i } + Err(_) => { 2 } + } + } + }; + let min_bytes = formats.iter().fold(2, |max, next| cmp::max(max, next.itembytes)); + if line_bytes % min_bytes != 0 { + show_warning!("invalid width {}; using {} instead", line_bytes, min_bytes); + line_bytes = min_bytes; + } + + odfunc(line_bytes, &input_offset_base, &inputs, &formats[..]) } -const LINEBYTES:usize = 16; - -fn odfunc(input_offset_base: &Radix, fnames: &[InputSource], formats: &[OdFormat]) -> i32 { +fn odfunc(line_bytes: usize, input_offset_base: &Radix, fnames: &[InputSource], formats: &[OdFormat]) -> i32 { let mut mf = MultifileReader::new(fnames); let mut addr = 0; - let bytes = &mut [b'\x00'; LINEBYTES]; + let mut bytes: Vec = vec![b'\x00'; line_bytes]; loop { // print each line data (or multi-format raster of several lines describing the same data). print_with_radix(input_offset_base, addr); // print offset // if printing in multiple formats offset is printed only once - match mf.f_read(bytes) { + match mf.f_read(bytes.as_mut_slice()) { Ok(0) => { print!("\n"); break; diff --git a/tests/test_od.rs b/tests/test_od.rs index 8836faa58..98d399826 100644 --- a/tests/test_od.rs +++ b/tests/test_od.rs @@ -223,3 +223,54 @@ fn mit_die_umlauten_getesten() { "0000000 U n i v e r s i t ä ** t T ü **\n0000020 b i n g e n\n0000026") } */ + +#[test] +fn test_width(){ + + let input : [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let expected_output = unindent(" + 0000000 000000 000000 + 0000004 000000 000000 + 0000010 + "); + + let result = new_ucmd!().arg("-w4").run_piped_stdin(&input[..]); + + assert_empty_stderr!(result); + assert!(result.success); + assert_eq!(result.stdout, expected_output); +} + +#[test] +fn test_invalid_width(){ + + let input : [u8; 4] = [0x00, 0x00, 0x00, 0x00]; + let expected_output = unindent(" + 0000000 000000 + 0000002 000000 + 0000004 + "); + + let result = new_ucmd!().arg("-w5").run_piped_stdin(&input[..]); + + assert_eq!(result.stderr, "od: warning: invalid width 5; using 2 instead\n"); + assert!(result.success); + assert_eq!(result.stdout, expected_output); +} + +#[test] +fn test_width_without_value(){ + + let input : [u8; 40] = [0 ; 40]; + let expected_output = unindent(" + 0000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 + 0000040 000000 000000 000000 000000 + 0000050 + "); + + let result = new_ucmd!().arg("-w").run_piped_stdin(&input[..]); + + assert_empty_stderr!(result); + assert!(result.success); + assert_eq!(result.stdout, expected_output); +}