mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 11:07:44 +00:00
od: refactor: create struct for formatting info
also properly document the alignment algorithm.
This commit is contained in:
parent
83a1ff404f
commit
2c24911d9c
2 changed files with 272 additions and 68 deletions
96
src/od/od.rs
96
src/od/od.rs
|
@ -28,6 +28,7 @@ mod parse_formats;
|
|||
mod parse_inputs;
|
||||
mod inputoffset;
|
||||
mod inputdecoder;
|
||||
mod output_info;
|
||||
#[cfg(test)]
|
||||
mod mockstream;
|
||||
|
||||
|
@ -39,14 +40,14 @@ use partialreader::*;
|
|||
use peekreader::*;
|
||||
use formatteriteminfo::*;
|
||||
use parse_nrofbytes::parse_number_of_bytes;
|
||||
use parse_formats::{parse_format_flags, ParsedFormatterItemInfo};
|
||||
use parse_formats::parse_format_flags;
|
||||
use prn_char::format_ascii_dump;
|
||||
use parse_inputs::{parse_inputs, CommandLineInputs};
|
||||
use inputoffset::{InputOffset, Radix};
|
||||
use inputdecoder::{InputDecoder,MemoryDecoder};
|
||||
use output_info::OutputInfo;
|
||||
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
const MAX_BYTES_PER_UNIT: usize = 8;
|
||||
const PEEK_BUFFER_SIZE: usize = 4; // utf-8 can be 4 bytes
|
||||
|
||||
static USAGE: &'static str =
|
||||
|
@ -93,6 +94,8 @@ Any type specification can have a "z" suffic, which will add a ASCII dump at
|
|||
If an error occurred, a diagnostic message will be printed to stderr, and the
|
||||
exitcode will be non-zero."#;
|
||||
|
||||
/// parses and validates commandline parameters, prepares data structures,
|
||||
/// opens the input and calls `odfunc` to process the input.
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = getopts::Options::new();
|
||||
|
||||
|
@ -233,65 +236,27 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
};
|
||||
|
||||
let mut input = open_input_peek_reader(&input_strings, skip_bytes, read_bytes);
|
||||
|
||||
let mut input_decoder = InputDecoder::new(&mut input, line_bytes, PEEK_BUFFER_SIZE, byte_order);
|
||||
|
||||
let mut input_offset = InputOffset::new(Radix::Octal, skip_bytes, label);
|
||||
if let Err(e) = input_offset.parse_radix_from_commandline(matches.opt_str("A")) {
|
||||
disp_err!("Invalid -A/--address-radix\n{}", e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
odfunc(&mut input_decoder, &mut input_offset, line_bytes, &formats[..],
|
||||
output_duplicates)
|
||||
let mut input = open_input_peek_reader(&input_strings, skip_bytes, read_bytes);
|
||||
let mut input_decoder = InputDecoder::new(&mut input, line_bytes, PEEK_BUFFER_SIZE, byte_order);
|
||||
|
||||
let output_info = OutputInfo::new(line_bytes, &formats[..], output_duplicates);
|
||||
|
||||
odfunc(&mut input_offset, &mut input_decoder, &output_info)
|
||||
}
|
||||
|
||||
// TODO: refactor, too many arguments
|
||||
fn odfunc<I>(input_decoder: &mut InputDecoder<I>, input_offset: &mut InputOffset, line_bytes: usize,
|
||||
formats: &[ParsedFormatterItemInfo], output_duplicates: bool) -> i32
|
||||
/// Loops through the input line by line, calling print_bytes to take care of the output.
|
||||
fn odfunc<I>(input_offset: &mut InputOffset, input_decoder: &mut InputDecoder<I>,
|
||||
output_info: &OutputInfo) -> i32
|
||||
where I : PeekRead+HasError {
|
||||
|
||||
let mut duplicate_line = false;
|
||||
let mut previous_bytes: Vec<u8> = Vec::new();
|
||||
|
||||
let byte_size_block = formats.iter().fold(1, |max, next| cmp::max(max, next.formatter_item_info.byte_size));
|
||||
let print_width_block = formats
|
||||
.iter()
|
||||
.fold(1, |max, next| {
|
||||
cmp::max(max, next.formatter_item_info.print_width * (byte_size_block / next.formatter_item_info.byte_size))
|
||||
});
|
||||
let print_width_line = print_width_block * (line_bytes / byte_size_block);
|
||||
|
||||
if byte_size_block > MAX_BYTES_PER_UNIT {
|
||||
panic!("{}-bits types are unsupported. Current max={}-bits.",
|
||||
8 * byte_size_block,
|
||||
8 * MAX_BYTES_PER_UNIT);
|
||||
}
|
||||
|
||||
let mut spaced_formatters: Vec<SpacedFormatterItemInfo> = formats
|
||||
.iter()
|
||||
.map(|f| SpacedFormatterItemInfo { frm: *f, spacing: [0; MAX_BYTES_PER_UNIT] })
|
||||
.collect();
|
||||
|
||||
// calculate proper alignment for each item
|
||||
for sf in &mut spaced_formatters {
|
||||
let mut byte_size = sf.frm.formatter_item_info.byte_size;
|
||||
let mut items_in_block = byte_size_block / byte_size;
|
||||
let thisblock_width = sf.frm.formatter_item_info.print_width * items_in_block;
|
||||
let mut missing_spacing = print_width_block - thisblock_width;
|
||||
|
||||
while items_in_block > 0 {
|
||||
let avg_spacing: usize = missing_spacing / items_in_block;
|
||||
for i in 0..items_in_block {
|
||||
sf.spacing[i * byte_size] += avg_spacing;
|
||||
missing_spacing -= avg_spacing;
|
||||
}
|
||||
// this assumes the size of all types is a power of 2 (1, 2, 4, 8, 16, ...)
|
||||
items_in_block /= 2;
|
||||
byte_size *= 2;
|
||||
}
|
||||
}
|
||||
let line_bytes = output_info.byte_size_line;
|
||||
|
||||
loop {
|
||||
// print each line data (or multi-format raster of several lines describing the same data).
|
||||
|
@ -308,7 +273,7 @@ fn odfunc<I>(input_decoder: &mut InputDecoder<I>, input_offset: &mut InputOffset
|
|||
// not enough byte for a whole element, this should only happen on the last line.
|
||||
if length != line_bytes {
|
||||
// set zero bytes in the part of the buffer that will be used, but is not filled.
|
||||
let mut max_used = length + MAX_BYTES_PER_UNIT;
|
||||
let mut max_used = length + output_info.byte_size_block;
|
||||
if max_used > line_bytes {
|
||||
max_used = line_bytes;
|
||||
}
|
||||
|
@ -316,7 +281,7 @@ fn odfunc<I>(input_decoder: &mut InputDecoder<I>, input_offset: &mut InputOffset
|
|||
memory_decoder.zero_out_buffer(length, max_used);
|
||||
}
|
||||
|
||||
if !output_duplicates
|
||||
if !output_info.output_duplicates
|
||||
&& length == line_bytes
|
||||
&& memory_decoder.get_buffer(0) == &previous_bytes[..] {
|
||||
if !duplicate_line {
|
||||
|
@ -332,7 +297,7 @@ fn odfunc<I>(input_decoder: &mut InputDecoder<I>, input_offset: &mut InputOffset
|
|||
}
|
||||
|
||||
print_bytes(&input_offset.format_byte_offset(), &memory_decoder,
|
||||
&spaced_formatters, byte_size_block, print_width_line);
|
||||
&output_info);
|
||||
}
|
||||
|
||||
input_offset.increase_position(length);
|
||||
|
@ -352,25 +317,25 @@ fn odfunc<I>(input_decoder: &mut InputDecoder<I>, input_offset: &mut InputOffset
|
|||
}
|
||||
}
|
||||
|
||||
fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder,
|
||||
formats: &[SpacedFormatterItemInfo], byte_size_block: usize, print_width_line: usize) {
|
||||
/// Outputs a single line of input, into one or more lines human readable output.
|
||||
fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder, output_info: &OutputInfo) {
|
||||
let mut first = true; // First line of a multi-format raster.
|
||||
for f in formats {
|
||||
for f in output_info.spaced_formatters_iter() {
|
||||
let mut output_text = String::new();
|
||||
|
||||
let mut b = 0;
|
||||
while b < input_decoder.length() {
|
||||
output_text.push_str(&format!("{:>width$}",
|
||||
"",
|
||||
width = f.spacing[b % byte_size_block]));
|
||||
width = f.spacing[b % output_info.byte_size_block]));
|
||||
|
||||
match f.frm.formatter_item_info.formatter {
|
||||
match f.formatter_item_info.formatter {
|
||||
FormatWriter::IntWriter(func) => {
|
||||
let p = input_decoder.read_uint(b, f.frm.formatter_item_info.byte_size);
|
||||
let p = input_decoder.read_uint(b, f.formatter_item_info.byte_size);
|
||||
output_text.push_str(&func(p));
|
||||
}
|
||||
FormatWriter::FloatWriter(func) => {
|
||||
let p = input_decoder.read_float(b, f.frm.formatter_item_info.byte_size);
|
||||
let p = input_decoder.read_float(b, f.formatter_item_info.byte_size);
|
||||
output_text.push_str(&func(p));
|
||||
}
|
||||
FormatWriter::MultibyteWriter(func) => {
|
||||
|
@ -378,11 +343,11 @@ fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder,
|
|||
}
|
||||
}
|
||||
|
||||
b += f.frm.formatter_item_info.byte_size;
|
||||
b += f.formatter_item_info.byte_size;
|
||||
}
|
||||
|
||||
if f.frm.add_ascii_dump {
|
||||
let missing_spacing = print_width_line.saturating_sub(output_text.chars().count());
|
||||
if f.add_ascii_dump {
|
||||
let missing_spacing = output_info.print_width_line.saturating_sub(output_text.chars().count());
|
||||
output_text.push_str(&format!("{:>width$} {}",
|
||||
"",
|
||||
format_ascii_dump(input_decoder.get_buffer(0)),
|
||||
|
@ -423,8 +388,3 @@ fn open_input_peek_reader<'a>(input_strings: &'a Vec<String>, skip_bytes: usize,
|
|||
let input = PeekReader::new(pr);
|
||||
input
|
||||
}
|
||||
|
||||
struct SpacedFormatterItemInfo {
|
||||
frm: ParsedFormatterItemInfo,
|
||||
spacing: [usize; MAX_BYTES_PER_UNIT],
|
||||
}
|
||||
|
|
244
src/od/output_info.rs
Normal file
244
src/od/output_info.rs
Normal file
|
@ -0,0 +1,244 @@
|
|||
use std::cmp;
|
||||
use std::slice::Iter;
|
||||
use parse_formats::ParsedFormatterItemInfo;
|
||||
use formatteriteminfo::FormatterItemInfo;
|
||||
|
||||
/// Size in bytes of the max datatype. ie set to 16 for 128-bit numbers.
|
||||
const MAX_BYTES_PER_UNIT: usize = 8;
|
||||
|
||||
/// Contains information to output single output line in human readable form
|
||||
pub struct SpacedFormatterItemInfo {
|
||||
/// Contains a function pointer to output data, and information about the output format.
|
||||
pub formatter_item_info: FormatterItemInfo,
|
||||
/// Contains the number of spaces to add to align data with other output formats.
|
||||
///
|
||||
/// If the corresponding data is a single byte, each entry in this array contains
|
||||
/// the number of spaces to insert when outputting each byte. If the corresponding
|
||||
/// data is multi-byte, only the fist byte position is used. For example a 32-bit
|
||||
/// datatype, could use positions 0, 4, 8, 12, ....
|
||||
/// As each block is formatted identically, only the spacing for a single block is set.
|
||||
pub spacing: [usize; MAX_BYTES_PER_UNIT],
|
||||
/// if set adds a ascii dump at the end of the line
|
||||
pub add_ascii_dump: bool,
|
||||
}
|
||||
|
||||
/// Contains information about all output lines.
|
||||
pub struct OutputInfo {
|
||||
/// The number of bytes of a line.
|
||||
pub byte_size_line: usize,
|
||||
/// The width of a line in human readable format.
|
||||
pub print_width_line: usize,
|
||||
|
||||
/// The number of bytes in a block. (This is the size of the largest datatype in `spaced_formatters`.)
|
||||
pub byte_size_block: usize,
|
||||
/// The width of a block in human readable format. (The size of the largest format.)
|
||||
pub print_width_block: usize,
|
||||
/// All formats.
|
||||
spaced_formatters: Vec<SpacedFormatterItemInfo>,
|
||||
/// determines if duplicate output lines should be printed, or
|
||||
/// skipped with a "*" showing one or more skipped lines.
|
||||
pub output_duplicates: bool,
|
||||
}
|
||||
|
||||
|
||||
impl OutputInfo {
|
||||
/// Returns an iterator over the `SpacedFormatterItemInfo` vector.
|
||||
pub fn spaced_formatters_iter(&self) -> Iter<SpacedFormatterItemInfo> {
|
||||
self.spaced_formatters.iter()
|
||||
}
|
||||
|
||||
/// Creates a new `OutputInfo` based on the parameters
|
||||
pub fn new(line_bytes: usize, formats: &[ParsedFormatterItemInfo], output_duplicates: bool) -> OutputInfo {
|
||||
|
||||
let byte_size_block = formats.iter().fold(1, |max, next| cmp::max(max, next.formatter_item_info.byte_size));
|
||||
let print_width_block = formats
|
||||
.iter()
|
||||
.fold(1, |max, next| {
|
||||
cmp::max(max, next.formatter_item_info.print_width * (byte_size_block / next.formatter_item_info.byte_size))
|
||||
});
|
||||
let print_width_line = print_width_block * (line_bytes / byte_size_block);
|
||||
|
||||
let spaced_formatters = OutputInfo::create_spaced_formatter_info(&formats, byte_size_block, print_width_block);
|
||||
|
||||
OutputInfo {
|
||||
byte_size_line: line_bytes,
|
||||
print_width_line: print_width_line,
|
||||
byte_size_block: byte_size_block,
|
||||
print_width_block: print_width_block,
|
||||
spaced_formatters: spaced_formatters,
|
||||
output_duplicates: output_duplicates,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_spaced_formatter_info(formats: &[ParsedFormatterItemInfo],
|
||||
byte_size_block: usize, print_width_block: usize) -> Vec<SpacedFormatterItemInfo> {
|
||||
formats
|
||||
.iter()
|
||||
.map(|f| SpacedFormatterItemInfo {
|
||||
formatter_item_info: f.formatter_item_info,
|
||||
add_ascii_dump: f.add_ascii_dump,
|
||||
spacing: OutputInfo::calculate_alignment(f, byte_size_block, print_width_block)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// calculates proper alignment for a single line of output
|
||||
///
|
||||
/// Multiple representations of the same data, will be right-aligned for easy reading.
|
||||
/// For example a 64 bit octal and a 32-bit decimal with a 16-bit hexadecimal looks like this:
|
||||
/// ```
|
||||
/// 1777777777777777777777 1777777777777777777777
|
||||
/// 4294967295 4294967295 4294967295 4294967295
|
||||
/// ffff ffff ffff ffff ffff ffff ffff ffff
|
||||
/// ```
|
||||
/// In this example is additional spacing before the first and third decimal number,
|
||||
/// and there is additional spacing before the 1st, 3rd, 5th and 7th hexadecimal number.
|
||||
/// This way both the octal and decimal, aswell the decimal and hexadecimal numbers
|
||||
/// left align. Note that the alignment below both octal numbers is identical.
|
||||
///
|
||||
/// This function calculates the required spacing for a single line, given the size
|
||||
/// of a block, and the width of a block. The size of a block is the largest type
|
||||
/// and the width is width of the the type which needs the most space to print that
|
||||
/// number of bytes. So both numbers might refer to different types. All widths
|
||||
/// include a space at the front. For example the width of a 8-bit hexadecimal,
|
||||
/// is 3 characters, for example " FF".
|
||||
///
|
||||
/// This algorithm first calculates how many spaces needs to be added, based the
|
||||
/// block size and the size of the type, and the widths of the block and the type.
|
||||
/// The required spaces are spread across the available positions.
|
||||
/// If the blocksize is 8, and the size of the type is 8 too, there will be just
|
||||
/// one value in a block, so all spacing will be assigned to position 0.
|
||||
/// If the blocksize is 8, and the size of the type is 2, the spacing will be
|
||||
/// spread across position 0, 2, 4, 6. All 4 positions will get an additional
|
||||
/// space as long as there are more then 4 spaces available. If there are 2
|
||||
/// spaces available, they will be assigend to position 0 and 4. If there is
|
||||
/// 1 space available, it will be assigned to position 0. This will be combined,
|
||||
/// For example 7 spaces will be assigned to position 0, 2, 4, 6 like: 3, 1, 2, 1.
|
||||
/// And 7 spaces with 2 positions will be assigned to position 0 and 4 like 4, 3.
|
||||
///
|
||||
/// Here is another example showing the alignment of 64-bit unsigned decimal numbers,
|
||||
/// 32-bit hexadecimal number, 16-bit octal numbers and 8-bit hexadecimal numbers:
|
||||
/// ```
|
||||
/// 18446744073709551615 18446744073709551615
|
||||
/// ffffffff ffffffff ffffffff ffffffff
|
||||
/// 177777 177777 177777 177777 177777 177777 177777 177777
|
||||
/// ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
|
||||
/// ```
|
||||
///
|
||||
/// This algorithm assumes the size of all types is a power of 2 (1, 2, 4, 8, 16, ...)
|
||||
/// Increase MAX_BYTES_PER_UNIT to allow larger types.
|
||||
fn calculate_alignment(sf: &TypeSizeInfo, byte_size_block: usize,
|
||||
print_width_block: usize) -> [usize; MAX_BYTES_PER_UNIT] {
|
||||
|
||||
if byte_size_block > MAX_BYTES_PER_UNIT {
|
||||
panic!("{}-bits types are unsupported. Current max={}-bits.",
|
||||
8 * byte_size_block,
|
||||
8 * MAX_BYTES_PER_UNIT);
|
||||
}
|
||||
let mut spacing = [0; MAX_BYTES_PER_UNIT];
|
||||
|
||||
let mut byte_size = sf.byte_size();
|
||||
let mut items_in_block = byte_size_block / byte_size;
|
||||
let thisblock_width = sf.print_width() * items_in_block;
|
||||
let mut missing_spacing = print_width_block - thisblock_width;
|
||||
|
||||
while items_in_block > 0 {
|
||||
let avg_spacing: usize = missing_spacing / items_in_block;
|
||||
for i in 0..items_in_block {
|
||||
spacing[i * byte_size] += avg_spacing;
|
||||
missing_spacing -= avg_spacing;
|
||||
}
|
||||
|
||||
items_in_block /= 2;
|
||||
byte_size *= 2;
|
||||
}
|
||||
|
||||
spacing
|
||||
}
|
||||
}
|
||||
|
||||
trait TypeSizeInfo {
|
||||
fn byte_size(&self) -> usize;
|
||||
fn print_width(&self) -> usize;
|
||||
}
|
||||
|
||||
impl TypeSizeInfo for ParsedFormatterItemInfo {
|
||||
fn byte_size(&self) -> usize { self.formatter_item_info.byte_size }
|
||||
fn print_width(&self) -> usize { self.formatter_item_info.print_width }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
struct TypeInfo {
|
||||
byte_size: usize,
|
||||
print_width: usize,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl TypeSizeInfo for TypeInfo {
|
||||
fn byte_size(&self) -> usize { self.byte_size }
|
||||
fn print_width(&self) -> usize { self.print_width }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calculate_alignment() {
|
||||
|
||||
// For this example `byte_size_block` is 8 and 'print_width_block' is 23:
|
||||
// 1777777777777777777777 1777777777777777777777
|
||||
// 4294967295 4294967295 4294967295 4294967295
|
||||
// ffff ffff ffff ffff ffff ffff ffff ffff
|
||||
|
||||
// the first line has no additional spacing:
|
||||
assert_eq!([0, 0, 0, 0, 0, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:8, print_width:23}, 8, 23));
|
||||
// the second line a single space at the start of the block:
|
||||
assert_eq!([1, 0, 0, 0, 0, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:4, print_width:11}, 8, 23));
|
||||
// the third line two spaces at pos 0, and 1 space at pos 4:
|
||||
assert_eq!([2, 0, 0, 0, 1, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:2, print_width:5}, 8, 23));
|
||||
|
||||
// For this example `byte_size_block` is 8 and 'print_width_block' is 28:
|
||||
// 18446744073709551615 18446744073709551615
|
||||
// ffffffff ffffffff ffffffff ffffffff
|
||||
// 177777 177777 177777 177777 177777 177777 177777 177777
|
||||
// ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
|
||||
|
||||
assert_eq!([7, 0, 0, 0, 0, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:8, print_width:21}, 8, 28));
|
||||
assert_eq!([5, 0, 0, 0, 5, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:4, print_width:9}, 8, 28));
|
||||
assert_eq!([0, 0, 0, 0, 0, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:2, print_width:7}, 8, 28));
|
||||
assert_eq!([1, 0, 1, 0, 1, 0, 1, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:3}, 8, 28));
|
||||
|
||||
// 9 tests where 8 .. 16 spaces are spread across 8 positions
|
||||
assert_eq!([1, 1, 1, 1, 1, 1, 1, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+8));
|
||||
assert_eq!([2, 1, 1, 1, 1, 1, 1, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+9));
|
||||
assert_eq!([2, 1, 1, 1, 2, 1, 1, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+10));
|
||||
assert_eq!([3, 1, 1, 1, 2, 1, 1, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+11));
|
||||
assert_eq!([2, 1, 2, 1, 2, 1, 2, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+12));
|
||||
assert_eq!([3, 1, 2, 1, 2, 1, 2, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+13));
|
||||
assert_eq!([3, 1, 2, 1, 3, 1, 2, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+14));
|
||||
assert_eq!([4, 1, 2, 1, 3, 1, 2, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+15));
|
||||
assert_eq!([2, 2, 2, 2, 2, 2, 2, 2],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+16));
|
||||
|
||||
// 4 tests where 15 spaces are spread across 8, 4, 2 or 1 position(s)
|
||||
assert_eq!([4, 1, 2, 1, 3, 1, 2, 1],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:1, print_width:2}, 8, 16+15));
|
||||
assert_eq!([5, 0, 3, 0, 4, 0, 3, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:2, print_width:4}, 8, 16+15));
|
||||
assert_eq!([8, 0, 0, 0, 7, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:4, print_width:8}, 8, 16+15));
|
||||
assert_eq!([15, 0, 0, 0, 0, 0, 0, 0],
|
||||
OutputInfo::calculate_alignment(&TypeInfo{byte_size:8, print_width:16}, 8, 16+15));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue