od: implement --endian

This commit is contained in:
Wim Hueskes 2016-07-30 20:39:09 +02:00
parent d18be30c8a
commit f7d7beb79b
3 changed files with 58 additions and 23 deletions

View file

@ -1,32 +1,36 @@
// from: https://github.com/netvl/immeta/blob/4460ee/src/utils.rs#L76
// workaround until https://github.com/BurntSushi/byteorder/issues/41 has been fixed
// based on: https://github.com/netvl/immeta/blob/4460ee/src/utils.rs#L76
use std::io::{self, Read, BufRead, ErrorKind};
use byteorder::{self, ReadBytesExt, LittleEndian, BigEndian};
use byteorder::{NativeEndian, LittleEndian, BigEndian};
use byteorder::ByteOrder as ByteOrderTrait;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ByteOrder {
Little,
Big,
Native,
}
macro_rules! gen_byte_order_ops {
($($read_name:ident, $write_name:ident -> $tpe:ty),+) => {
impl ByteOrder {
$(
#[allow(dead_code)]
#[inline]
pub fn $read_name(self, source: &[u8]) -> $tpe {
match self {
ByteOrder::Little => LittleEndian::$read_name(source),
ByteOrder::Big => BigEndian::$read_name(source),
ByteOrder::Native => NativeEndian::$read_name(source),
}
}
#[allow(dead_code)]
pub fn $write_name(self, target: &mut [u8], n: $tpe) {
match self {
ByteOrder::Little => LittleEndian::$write_name(target, n),
ByteOrder::Big => BigEndian::$write_name(target, n),
ByteOrder::Native => NativeEndian::$write_name(target, n),
}
}
)+

View file

@ -17,6 +17,7 @@ extern crate byteorder;
extern crate uucore;
mod multifilereader;
mod byteorder_io;
mod prn_int;
mod prn_char;
mod prn_float;
@ -24,7 +25,7 @@ mod prn_float;
use std::cmp;
use std::io::Write;
use unindent::*;
use byteorder::*;
use byteorder_io::*;
use multifilereader::*;
use prn_int::*;
use prn_char::*;
@ -53,6 +54,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
"Skip bytes input bytes before formatting and writing.", "BYTES");
opts.optopt("N", "read-bytes",
"limit dump to BYTES input bytes", "BYTES");
opts.optopt("", "endian", "byte order to use for multi-byte formats", "big|little");
opts.optopt("S", "strings",
("output strings of at least BYTES graphic chars. 3 is assumed when \
BYTES is not specified."),
@ -117,6 +119,16 @@ pub fn uumain(args: Vec<String>) -> i32 {
}
};
let byte_order = match matches.opt_str("endian").as_ref().map(String::as_ref) {
None => { ByteOrder::Native },
Some("little") => { ByteOrder::Little },
Some("big") => { ByteOrder::Big },
Some(s) => {
disp_err!("Invalid argument --endian={}", s);
return 1;
}
};
// Gather up file names - args which don't start with '-'
let stdnionly = [InputSource::Stdin];
let inputs = args[1..]
@ -239,10 +251,10 @@ pub fn uumain(args: Vec<String>) -> i32 {
let output_duplicates = matches.opt_present("v");
odfunc(line_bytes, &input_offset_base, &inputs, &formats[..], output_duplicates)
odfunc(line_bytes, &input_offset_base, byte_order, &inputs, &formats[..], output_duplicates)
}
fn odfunc(line_bytes: usize, input_offset_base: &Radix,
fn odfunc(line_bytes: usize, input_offset_base: &Radix, byte_order: ByteOrder,
fnames: &[InputSource], formats: &[OdFormat], output_duplicates: bool) -> i32 {
let mut mf = MultifileReader::new(fnames);
@ -278,7 +290,7 @@ fn odfunc(line_bytes: usize, input_offset_base: &Radix,
duplicate_line = false;
previous_bytes.clone_from(&bytes);
print_bytes(&bytes, n, &print_with_radix(input_offset_base, addr), formats);
print_bytes(byte_order, &bytes, n, &print_with_radix(input_offset_base, addr), formats);
}
addr += n;
@ -296,7 +308,7 @@ fn odfunc(line_bytes: usize, input_offset_base: &Radix,
}
}
fn print_bytes(bytes: &[u8], length: usize, prefix: &str, formats: &[OdFormat]) {
fn print_bytes(byte_order: ByteOrder, bytes: &[u8], length: usize, prefix: &str, formats: &[OdFormat]) {
let mut first = true; // First line of a multi-format raster.
for f in formats {
let mut output_text = String::new();
@ -313,13 +325,13 @@ fn print_bytes(bytes: &[u8], length: usize, prefix: &str, formats: &[OdFormat])
bytes[b] as u64
}
2 => {
LittleEndian::read_u16(&bytes[b..nextb]) as u64
byte_order.read_u16(&bytes[b..nextb]) as u64
}
4 => {
LittleEndian::read_u32(&bytes[b..nextb]) as u64
byte_order.read_u32(&bytes[b..nextb]) as u64
}
8 => {
LittleEndian::read_u64(&bytes[b..nextb])
byte_order.read_u64(&bytes[b..nextb])
}
_ => { panic!("Invalid itembytes: {}", f.itembytes); }
};
@ -328,10 +340,10 @@ fn print_bytes(bytes: &[u8], length: usize, prefix: &str, formats: &[OdFormat])
FormatWriter::FloatWriter(func) => {
let p: f64 = match f.itembytes {
4 => {
LittleEndian::read_f32(&bytes[b..nextb]) as f64
byte_order.read_f32(&bytes[b..nextb]) as f64
}
8 => {
LittleEndian::read_f64(&bytes[b..nextb])
byte_order.read_f64(&bytes[b..nextb])
}
_ => { panic!("Invalid itembytes: {}", f.itembytes); }
};

View file

@ -35,7 +35,7 @@ fn test_file() {
}
}
let result = new_ucmd!().arg(file.as_os_str()).run();
let result = new_ucmd!().arg("--endian=little").arg(file.as_os_str()).run();
assert_empty_stderr!(result);
assert!(result.success);
@ -64,7 +64,7 @@ fn test_2files() {
}
}
let result = new_ucmd!().arg(file1.as_os_str()).arg(file2.as_os_str()).run();
let result = new_ucmd!().arg("--endian=little").arg(file1.as_os_str()).arg(file2.as_os_str()).run();
assert_empty_stderr!(result);
assert!(result.success);
@ -91,7 +91,7 @@ fn test_no_file() {
fn test_from_stdin() {
let input = "abcdefghijklmnopqrstuvwxyz\n";
let result = new_ucmd!().run_piped_stdin(input.as_bytes());
let result = new_ucmd!().arg("--endian=little").run_piped_stdin(input.as_bytes());
assert_empty_stderr!(result);
assert!(result.success);
@ -117,7 +117,7 @@ fn test_from_mixed() {
}
}
let result = new_ucmd!().arg(file1.as_os_str()).arg("--").arg(file3.as_os_str()).run_piped_stdin(data2.as_bytes());
let result = new_ucmd!().arg("--endian=little").arg(file1.as_os_str()).arg("--").arg(file3.as_os_str()).run_piped_stdin(data2.as_bytes());
assert_empty_stderr!(result);
assert!(result.success);
@ -158,7 +158,7 @@ fn test_dec() {
0000000 0 1 2 3 32767 -32768 -32767
0000016
");
let result = new_ucmd!().arg("-i").run_piped_stdin(&input[..]);
let result = new_ucmd!().arg("--endian=little").arg("-i").run_piped_stdin(&input[..]);
assert_empty_stderr!(result);
assert!(result.success);
@ -175,7 +175,7 @@ fn test_hex16(){
0000000 2301 6745 ab89 efcd 00ff
0000011
");
let result = new_ucmd!().arg("-x").run_piped_stdin(&input[..]);
let result = new_ucmd!().arg("--endian=little").arg("-x").run_piped_stdin(&input[..]);
assert_empty_stderr!(result);
assert!(result.success);
@ -191,7 +191,7 @@ fn test_hex32(){
0000000 67452301 efcdab89 000000ff
0000011
");
let result = new_ucmd!().arg("-X").run_piped_stdin(&input[..]);
let result = new_ucmd!().arg("--endian=little").arg("-X").run_piped_stdin(&input[..]);
assert_empty_stderr!(result);
assert!(result.success);
@ -214,7 +214,7 @@ fn test_f32(){
0000020 NaN 1e-40 -1.1663108e-38
0000034
");
let result = new_ucmd!().arg("-f").run_piped_stdin(&input[..]);
let result = new_ucmd!().arg("--endian=little").arg("-f").run_piped_stdin(&input[..]);
assert_empty_stderr!(result);
assert!(result.success);
@ -236,7 +236,7 @@ fn test_f64(){
0000040 -2.0000000000000000
0000050
");
let result = new_ucmd!().arg("-F").run_piped_stdin(&input[..]);
let result = new_ucmd!().arg("--endian=little").arg("-F").run_piped_stdin(&input[..]);
assert_empty_stderr!(result);
assert!(result.success);
@ -326,3 +326,22 @@ fn test_suppress_duplicates(){
assert!(result.success);
assert_eq!(result.stdout, expected_output);
}
#[test]
fn test_big_endian() {
let input : [u8; 8] = [
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];// 0xc000000000000000 -2
let expected_output = unindent("
0000000 -2.0000000000000000
-2.0000000 0
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[..]);
assert_empty_stderr!(result);
assert!(result.success);
assert_eq!(result.stdout, expected_output);
}