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,67 +157,28 @@ 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)
}