1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

od: use structs to specify possible dump formats

remove extra padding too - preparing proper allignment
This commit is contained in:
Wim Hueskes 2016-07-30 23:59:10 +02:00
parent f7d7beb79b
commit 45895be96d
6 changed files with 216 additions and 128 deletions

View file

@ -0,0 +1,12 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FormatWriter {
IntWriter(fn(u64, usize, usize) -> String),
FloatWriter(fn(f64) -> String),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FormatterItemInfo {
pub byte_size: usize,
pub print_width: usize,
pub formatter: FormatWriter,
}

View file

@ -18,6 +18,7 @@ extern crate uucore;
mod multifilereader;
mod byteorder_io;
mod formatteriteminfo;
mod prn_int;
mod prn_char;
mod prn_float;
@ -30,6 +31,7 @@ use multifilereader::*;
use prn_int::*;
use prn_char::*;
use prn_float::*;
use formatteriteminfo::*;
//This is available in some versions of std, but not all that we target.
macro_rules! hashmap {
@ -155,68 +157,29 @@ pub fn uumain(args: Vec<String>) -> i32 {
})
.collect::<Vec<_>>();
// At the moment, char (-a & -c)formats need the driver to set up a
// line by inserting a different # of of spaces at the start.
struct OdFormater {
writer: FormatWriter,
offmarg: usize,
};
let oct = OdFormater {
writer: FormatWriter::IntWriter(format_item_oct), offmarg: 2
};
let hex = OdFormater {
writer: FormatWriter::IntWriter(format_item_hex), offmarg: 2
};
let dec_u = OdFormater {
writer: FormatWriter::IntWriter(format_item_dec_u), offmarg: 2
};
let dec_s = OdFormater {
writer: FormatWriter::IntWriter(format_item_dec_s), offmarg: 2
};
let a_char = OdFormater {
writer: FormatWriter::IntWriter(format_item_a), offmarg: 1
};
let c_char = OdFormater {
writer: FormatWriter::IntWriter(format_item_c), offmarg: 1
};
let flo32 = OdFormater {
writer: FormatWriter::FloatWriter(format_item_flo32), offmarg: 0
};
let flo64 = OdFormater {
writer: FormatWriter::FloatWriter(format_item_flo64), offmarg: 0
};
fn mkfmt(itembytes: usize, fmtspec: &OdFormater) -> OdFormat {
OdFormat {
itembytes: itembytes,
writer: fmtspec.writer,
offmarg: fmtspec.offmarg,
}
}
// TODO: -t fmts
let known_formats = hashmap![
"a" => (1, &a_char),
"B" => (2, &oct) ,
"b" => (1, &oct),
"c" => (1, &c_char),
"D" => (4, &dec_u),
"e" => (8, &flo64),
"F" => (8, &flo64),
"f" => (4, &flo32),
"H" => (4, &hex),
"X" => (4, &hex) ,
"o" => (2, &oct),
"x" => (2, &hex),
"h" => (2, &hex),
"a" => FORMAT_ITEM_A,
"B" => FORMAT_ITEM_OCT16,
"b" => FORMAT_ITEM_OCT8,
"c" => FORMAT_ITEM_C,
"D" => FORMAT_ITEM_DEC32U,
"e" => FORMAT_ITEM_F64,
"F" => FORMAT_ITEM_F64,
"f" => FORMAT_ITEM_F32,
"H" => FORMAT_ITEM_HEX32,
"X" => FORMAT_ITEM_HEX32,
"o" => FORMAT_ITEM_OCT16,
"x" => FORMAT_ITEM_HEX16,
"h" => FORMAT_ITEM_HEX16,
"I" => (2, &dec_s),
"L" => (2, &dec_s),
"i" => (2, &dec_s),
"I" => FORMAT_ITEM_DEC16S,
"L" => FORMAT_ITEM_DEC16S,
"i" => FORMAT_ITEM_DEC16S,
"O" => (4, &oct),
"s" => (2, &dec_u)
];
"O" => FORMAT_ITEM_OCT32,
"s" => FORMAT_ITEM_DEC16U
];
let mut formats = Vec::new();
@ -224,14 +187,13 @@ pub fn uumain(args: Vec<String>) -> i32 {
match known_formats.get(flag) {
None => {} // not every option is a format
Some(r) => {
let (itembytes, fmtspec) = *r;
formats.push(mkfmt(itembytes, fmtspec))
formats.push(*r)
}
}
}
if formats.is_empty() {
formats.push(mkfmt(2, &oct)); // 2 byte octal is the default
formats.push(FORMAT_ITEM_OCT16); // 2 byte octal is the default
}
let mut line_bytes = match matches.opt_default("w", "32") {
@ -243,7 +205,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
}
}
};
let min_bytes = formats.iter().fold(2, |max, next| cmp::max(max, next.itembytes));
let min_bytes = formats.iter().fold(2, |max, next| cmp::max(max, next.byte_size));
if line_bytes % min_bytes != 0 {
show_warning!("invalid width {}; using {} instead", line_bytes, min_bytes);
line_bytes = min_bytes;
@ -255,7 +217,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
}
fn odfunc(line_bytes: usize, input_offset_base: &Radix, byte_order: ByteOrder,
fnames: &[InputSource], formats: &[OdFormat], output_duplicates: bool) -> i32 {
fnames: &[InputSource], formats: &[FormatterItemInfo], output_duplicates: bool) -> i32 {
let mut mf = MultifileReader::new(fnames);
let mut addr = 0;
@ -308,19 +270,17 @@ fn odfunc(line_bytes: usize, input_offset_base: &Radix, byte_order: ByteOrder,
}
}
fn print_bytes(byte_order: ByteOrder, bytes: &[u8], length: usize, prefix: &str, formats: &[OdFormat]) {
fn print_bytes(byte_order: ByteOrder, bytes: &[u8], length: usize, prefix: &str, formats: &[FormatterItemInfo]) {
let mut first = true; // First line of a multi-format raster.
for f in formats {
let mut output_text = String::new();
output_text.push_str(&format!("{:>width$}", "", width = f.offmarg));// 4 spaces after offset - we print 2 more before each word
let mut b = 0;
while b < length {
let nextb = b + f.itembytes;
match f.writer {
let nextb = b + f.byte_size;
match f.formatter {
FormatWriter::IntWriter(func) => {
let p: u64 = match f.itembytes {
let p: u64 = match f.byte_size {
1 => {
bytes[b] as u64
}
@ -333,19 +293,19 @@ fn print_bytes(byte_order: ByteOrder, bytes: &[u8], length: usize, prefix: &str,
8 => {
byte_order.read_u64(&bytes[b..nextb])
}
_ => { panic!("Invalid itembytes: {}", f.itembytes); }
_ => { panic!("Invalid byte_size: {}", f.byte_size); }
};
output_text.push_str(&func(p, f.itembytes));
output_text.push_str(&func(p, f.byte_size, f.print_width));
}
FormatWriter::FloatWriter(func) => {
let p: f64 = match f.itembytes {
let p: f64 = match f.byte_size {
4 => {
byte_order.read_f32(&bytes[b..nextb]) as f64
}
8 => {
byte_order.read_f64(&bytes[b..nextb])
}
_ => { panic!("Invalid itembytes: {}", f.itembytes); }
_ => { panic!("Invalid byte_size: {}", f.byte_size); }
};
output_text.push_str(&func(p));
}
@ -400,15 +360,3 @@ fn print_with_radix(r: &Radix, x: usize) -> String{
Radix::Binary => format!("{:07b}", x)
}
}
#[derive(Clone, Copy)]
enum FormatWriter {
IntWriter(fn(u64, usize) -> String),
FloatWriter(fn(f64) -> String),
}
struct OdFormat {
itembytes: usize,
writer: FormatWriter,
offmarg: usize,
}

View file

@ -1,3 +1,16 @@
use formatteriteminfo::*;
pub static FORMAT_ITEM_A: FormatterItemInfo = FormatterItemInfo {
byte_size: 1,
print_width: 3,
formatter: FormatWriter::IntWriter(format_item_a),
};
pub static FORMAT_ITEM_C: FormatterItemInfo = FormatterItemInfo {
byte_size: 1,
print_width: 3,
formatter: FormatWriter::IntWriter(format_item_c),
};
// TODO: multi-byte chars
// Quoth the man page: Multi-byte characters are displayed in the area corresponding to the first byte of the character. The remaining bytes are shown as `**'.
@ -24,7 +37,7 @@ static A_CHRS : [&'static str; 160] =
"90", "91", "92", "93", "94", "95", "96", "97",
"98", "99", "9a", "9b", "9c", "9d", "9e", "9f"];
pub fn format_item_a(p: u64, _: usize) -> String {
pub fn format_item_a(p: u64, _: usize, _: usize) -> String {
// itembytes == 1
let b = (p & 0xff) as u8;
format!("{:>4}", A_CHRS.get(b as usize).unwrap_or(&"?") // XXX od dose not actually do this, it just prints the byte
@ -51,7 +64,7 @@ static C_CHRS : [&'static str; 127] = [
"x", "y", "z", "{", "|", "}", "~" ];
pub fn format_item_c(p: u64, _: usize) -> String {
pub fn format_item_c(p: u64, _: usize, _: usize) -> String {
// itembytes == 1
let b = (p & 0xff) as usize;

View file

@ -1,6 +1,20 @@
use std::num::FpCategory;
use std::f32;
use std::f64;
use formatteriteminfo::*;
pub static FORMAT_ITEM_F32: FormatterItemInfo = FormatterItemInfo {
byte_size: 4,
print_width: 14,
formatter: FormatWriter::FloatWriter(format_item_flo32),
};
pub static FORMAT_ITEM_F64: FormatterItemInfo = FormatterItemInfo {
byte_size: 8,
print_width: 24,
formatter: FormatWriter::FloatWriter(format_item_flo64),
};
pub fn format_item_flo32(f: f64) -> String {
format!(" {}", format_flo32(f as f32))

View file

@ -1,24 +1,125 @@
// TODO: use some sort of byte iterator, instead of passing bytes in u64
pub fn format_item_oct(p: u64, itembytes: usize) -> String {
let itemwidth = 3 * itembytes;
let itemspace = 4 * itembytes - itemwidth;
use formatteriteminfo::*;
format!("{:>itemspace$}{:0width$o}",
"",
pub static FORMAT_ITEM_OCT8: FormatterItemInfo = FormatterItemInfo {
byte_size: 1,
print_width: 3,
formatter: FormatWriter::IntWriter(format_item_oct),
};
pub static FORMAT_ITEM_OCT16: FormatterItemInfo = FormatterItemInfo {
byte_size: 2,
print_width: 6,
formatter: FormatWriter::IntWriter(format_item_oct),
};
pub static FORMAT_ITEM_OCT32: FormatterItemInfo = FormatterItemInfo {
byte_size: 4,
print_width: 12,
formatter: FormatWriter::IntWriter(format_item_oct),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_OCT64: FormatterItemInfo = FormatterItemInfo {
byte_size: 8,
print_width: 24,
formatter: FormatWriter::IntWriter(format_item_oct),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_HEX8: FormatterItemInfo = FormatterItemInfo {
byte_size: 1,
print_width: 2,
formatter: FormatWriter::IntWriter(format_item_hex),
};
pub static FORMAT_ITEM_HEX16: FormatterItemInfo = FormatterItemInfo {
byte_size: 2,
print_width: 4,
formatter: FormatWriter::IntWriter(format_item_hex),
};
pub static FORMAT_ITEM_HEX32: FormatterItemInfo = FormatterItemInfo {
byte_size: 4,
print_width: 8,
formatter: FormatWriter::IntWriter(format_item_hex),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_HEX64: FormatterItemInfo = FormatterItemInfo {
byte_size: 8,
print_width: 16,
formatter: FormatWriter::IntWriter(format_item_hex),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_DEC8U: FormatterItemInfo = FormatterItemInfo {
byte_size: 1,
print_width: 3,
formatter: FormatWriter::IntWriter(format_item_dec_u),
};
pub static FORMAT_ITEM_DEC16U: FormatterItemInfo = FormatterItemInfo {
byte_size: 2,
print_width: 5,
formatter: FormatWriter::IntWriter(format_item_dec_u),
};
pub static FORMAT_ITEM_DEC32U: FormatterItemInfo = FormatterItemInfo {
byte_size: 4,
print_width: 10,
formatter: FormatWriter::IntWriter(format_item_dec_u),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_DEC64U: FormatterItemInfo = FormatterItemInfo {
byte_size: 8,
print_width: 19,
formatter: FormatWriter::IntWriter(format_item_dec_u),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_DEC8S: FormatterItemInfo = FormatterItemInfo {
byte_size: 1,
print_width: 4,
formatter: FormatWriter::IntWriter(format_item_dec_s),
};
pub static FORMAT_ITEM_DEC16S: FormatterItemInfo = FormatterItemInfo {
byte_size: 2,
print_width: 6,
formatter: FormatWriter::IntWriter(format_item_dec_s),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_DEC32S: FormatterItemInfo = FormatterItemInfo {
byte_size: 4,
print_width: 11,
formatter: FormatWriter::IntWriter(format_item_dec_s),
};
#[allow(dead_code)]
pub static FORMAT_ITEM_DEC64S: FormatterItemInfo = FormatterItemInfo {
byte_size: 8,
print_width: 20,
formatter: FormatWriter::IntWriter(format_item_dec_s),
};
// TODO: use some sort of byte iterator, instead of passing bytes in u64
pub fn format_item_oct(p: u64, _: usize, print_width: usize) -> String {
format!(" {:0width$o}",
p,
width = itemwidth,
itemspace = itemspace)
width = print_width)
}
pub fn format_item_hex(p: u64, itembytes: usize) -> String {
let itemwidth = 2 * itembytes;
let itemspace = 4 * itembytes - itemwidth;
pub fn format_item_hex(p: u64, _: usize, print_width: usize) -> String {
format!("{:>itemspace$}{:0width$x}",
"",
format!(" {:0width$x}",
p,
width = itemwidth,
itemspace = itemspace)
width = print_width)
}
@ -28,12 +129,12 @@ fn sign_extend(item: u64, itembytes: usize) -> i64{
}
pub fn format_item_dec_s(p: u64, itembytes: usize) -> String {
pub fn format_item_dec_s(p: u64, itembytes: usize, print_width: usize) -> String {
// sign extend
let s = sign_extend(p,itembytes);
format!("{:totalwidth$}", s, totalwidth = 4 * itembytes)
let s = sign_extend(p, itembytes);
format!(" {:width$}", s, width = print_width)
}
pub fn format_item_dec_u(p: u64, itembytes: usize) -> String {
format!("{:totalwidth$}", p, totalwidth = 4 * itembytes)
pub fn format_item_dec_u(p: u64, _: usize, print_width: usize) -> String {
format!(" {:width$}", p, width = print_width)
}

View file

@ -11,8 +11,8 @@ use self::unindent::*;
// octal dump of 'abcdefghijklmnopqrstuvwxyz\n'
static ALPHA_OUT: &'static str = "
0000000 061141 062143 063145 064147 065151 066153 067155 070157
0000020 071161 072163 073165 074167 075171 000012
0000000 061141 062143 063145 064147 065151 066153 067155 070157
0000020 071161 072163 073165 074167 075171 000012
0000033
";
@ -134,10 +134,10 @@ fn test_multiple_formats() {
assert_empty_stderr!(result);
assert!(result.success);
assert_eq!(result.stdout, unindent("
0000000 a b c d e f g h i j k l m n o p
141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 160
0000020 q r s t u v w x y z \\n
161 162 163 164 165 166 167 170 171 172 012
0000000 a b c d e f g h i j k l m n o p
141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 160
0000020 q r s t u v w x y z \\n
161 162 163 164 165 166 167 170 171 172 012
0000033
"));
@ -155,7 +155,7 @@ fn test_dec() {
0x00u8,0x80u8,
0x01u8,0x80u8,];
let expected_output = unindent("
0000000 0 1 2 3 32767 -32768 -32767
0000000 0 1 2 3 32767 -32768 -32767
0000016
");
let result = new_ucmd!().arg("--endian=little").arg("-i").run_piped_stdin(&input[..]);
@ -172,7 +172,7 @@ fn test_hex16(){
let input : [u8; 9] = [
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xff];
let expected_output = unindent("
0000000 2301 6745 ab89 efcd 00ff
0000000 2301 6745 ab89 efcd 00ff
0000011
");
let result = new_ucmd!().arg("--endian=little").arg("-x").run_piped_stdin(&input[..]);
@ -188,7 +188,7 @@ fn test_hex32(){
let input : [u8; 9] = [
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xff];
let expected_output = unindent("
0000000 67452301 efcdab89 000000ff
0000000 67452301 efcdab89 000000ff
0000011
");
let result = new_ucmd!().arg("--endian=little").arg("-X").run_piped_stdin(&input[..]);
@ -261,8 +261,8 @@ 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
0000000 000000 000000
0000004 000000 000000
0000010
");
@ -278,8 +278,8 @@ fn test_invalid_width(){
let input : [u8; 4] = [0x00, 0x00, 0x00, 0x00];
let expected_output = unindent("
0000000 000000
0000002 000000
0000000 000000
0000002 000000
0000004
");
@ -295,8 +295,8 @@ 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
0000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
0000040 000000 000000 000000 000000
0000050
");
@ -312,11 +312,11 @@ fn test_suppress_duplicates(){
let input = [0u8 ; 41];
let expected_output = unindent("
0000000 000000000000
0000 0000
0000000 000000000000
0000 0000
*
0000050 000000000000
0000
0000050 000000000000
0000
0000051
");
@ -335,8 +335,8 @@ fn test_big_endian() {
let expected_output = unindent("
0000000 -2.0000000000000000
-2.0000000 0
c0000000 00000000
c000 0000 0000 0000
c0000000 00000000
c000 0000 0000 0000
0000010
");
let result = new_ucmd!().arg("--endian=big").arg("-F").arg("-f").arg("-X").arg("-x").run_piped_stdin(&input[..]);