od: implement -w (width)

This commit is contained in:
Wim Hueskes 2016-07-23 21:49:43 +02:00
parent 1b01f02e9e
commit 167d7d3ca9
4 changed files with 78 additions and 8 deletions

1
Cargo.lock generated
View file

@ -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]]

View file

@ -12,6 +12,7 @@ getopts = "*"
libc = "*"
unindent = "*"
byteorder = "*"
uucore = { path="../uucore" }
[[bin]]
name = "od"

View file

@ -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<String>) -> 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<String>) -> 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::<usize>() {
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<u8> = 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;

View file

@ -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);
}