mirror of
https://github.com/uutils/coreutils
synced 2024-11-16 17:58:06 +00:00
od: implement --endian
This commit is contained in:
parent
d18be30c8a
commit
f7d7beb79b
3 changed files with 58 additions and 23 deletions
|
@ -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),
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
|
32
src/od/od.rs
32
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<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); }
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue