diff --git a/src/od/byteorder_io.rs b/src/od/byteorder_io.rs index ba49c3220..e72b4373b 100644 --- a/src/od/byteorder_io.rs +++ b/src/od/byteorder_io.rs @@ -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), } } )+ diff --git a/src/od/od.rs b/src/od/od.rs index 29f68c637..6ee2566d9 100644 --- a/src/od/od.rs +++ b/src/od/od.rs @@ -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) -> 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) -> 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) -> 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); } }; diff --git a/tests/test_od.rs b/tests/test_od.rs index b8d2d2198..a6dd2046f 100644 --- a/tests/test_od.rs +++ b/tests/test_od.rs @@ -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); +}