From c0b2da7c0119909c43b9c057455334cf0997b045 Mon Sep 17 00:00:00 2001 From: Chris Nikkel Date: Sat, 6 Aug 2016 18:25:11 -0700 Subject: [PATCH 1/2] uniq: add test for zero terminated input and output --- .../fixtures/uniq/sorted-zero-terminated.expected | Bin 0 -> 120 bytes tests/fixtures/uniq/sorted-zero-terminated.txt | Bin 0 -> 270 bytes tests/test_uniq.rs | 8 ++++++++ 3 files changed, 8 insertions(+) create mode 100644 tests/fixtures/uniq/sorted-zero-terminated.expected create mode 100644 tests/fixtures/uniq/sorted-zero-terminated.txt diff --git a/tests/fixtures/uniq/sorted-zero-terminated.expected b/tests/fixtures/uniq/sorted-zero-terminated.expected new file mode 100644 index 0000000000000000000000000000000000000000..94081d3640e8b5816049538930c3858ea6a0bc97 GIT binary patch literal 120 zcmY%3OauW1g-5L$6ciW~IFmpC#N7zyCW8Qoy9vxq0RaRz6$B96G!Q^=(?I~ibq4_$ F7XZ{5B^>|& literal 0 HcmV?d00001 diff --git a/tests/fixtures/uniq/sorted-zero-terminated.txt b/tests/fixtures/uniq/sorted-zero-terminated.txt new file mode 100644 index 0000000000000000000000000000000000000000..588f7b076462bbe7c42d8bb3d27539f6df9c9fc3 GIT binary patch literal 270 zcmY%3OauW1g-5L$6ciW~IFmpC#NCLEn+yUV*-c UCommand { static INPUT: &'static str = "sorted.txt"; static SKIP_CHARS: &'static str = "skip-chars.txt"; static SKIP_FIELDS: &'static str = "skip-fields.txt"; +static SORTED_ZERO_TERMINATED: &'static str = "sorted-zero-terminated.txt"; #[test] fn test_stdin_default() { @@ -92,3 +93,10 @@ fn test_stdin_repeated_only() { .args(&["-d"]).pipe_in_fixture(INPUT) .run().stdout_is_fixture("sorted-repeated-only.expected"); } + +#[test] +fn test_stdin_zero_terminated() { + new_ucmd() + .args(&["-z"]).pipe_in_fixture(SORTED_ZERO_TERMINATED) + .run().stdout_is_fixture("sorted-zero-terminated.expected"); +} \ No newline at end of file From cdfdc3a2bddec38577f6488f90f89beb9a18dc7d Mon Sep 17 00:00:00 2001 From: Chris Nikkel Date: Sat, 6 Aug 2016 18:25:52 -0700 Subject: [PATCH 2/2] uniq: add command line option -z for zero terminated input and output --- src/uniq/uniq.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/uniq/uniq.rs b/src/uniq/uniq.rs index 0c1200a25..aa1951613 100644 --- a/src/uniq/uniq.rs +++ b/src/uniq/uniq.rs @@ -34,6 +34,7 @@ struct Uniq { slice_start: Option, slice_stop: Option, ignore_case: bool, + zero_terminated: bool, } impl Uniq { @@ -41,9 +42,10 @@ impl Uniq { let mut lines: Vec = vec!(); let mut first_line_printed = false; let delimiters = &self.delimiters[..]; + let line_terminator = self.get_line_terminator(); - for io_line in reader.lines() { - let line = crash_if_err!(1, io_line); + for io_line in reader.split(line_terminator) { + let line = String::from_utf8(crash_if_err!(1, io_line)).unwrap(); if !lines.is_empty() && self.cmp_key(&lines[0]) != self.cmp_key(&line) { let print_delimiter = delimiters == "prepend" || (delimiters == "separate" && first_line_printed); first_line_printed |= self.print_lines(writer, &lines, print_delimiter); @@ -80,6 +82,14 @@ impl Uniq { } } + fn get_line_terminator(&self) -> u8 { + if self.zero_terminated { + 0 + } else { + '\n' as u8 + } + } + fn cmp_key(&self, line: &str) -> String { let fields_to_check = &self.skip_fields(line); let len = fields_to_check.len(); @@ -116,8 +126,10 @@ impl Uniq { } fn print_line(&self, writer: &mut BufWriter, line: &str, count: usize, print_delimiter: bool) { + let line_terminator = self.get_line_terminator(); + if print_delimiter { - crash_if_err!(1, writer.write_all(&['\n' as u8])); + crash_if_err!(1, writer.write_all(&[line_terminator])); } crash_if_err!(1, if self.show_counts { @@ -125,7 +137,7 @@ impl Uniq { } else { writer.write_all(line.as_bytes()) }); - crash_if_err!(1, writer.write_all("\n".as_bytes())); + crash_if_err!(1, writer.write_all(&[line_terminator])); } } @@ -153,6 +165,7 @@ pub fn uumain(args: Vec) -> i32 { opts.optopt("w", "check-chars", "compare no more than N characters in lines", "N"); opts.optflag("i", "ignore-case", "ignore differences in case when comparing"); opts.optflag("u", "unique", "only print unique lines"); + opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline"); opts.optflag("h", "help", "display this help and exit"); opts.optflag("V", "version", "output version information and exit"); @@ -202,6 +215,7 @@ pub fn uumain(args: Vec) -> i32 { slice_start: opt_parsed("skip-chars", &matches), slice_stop: opt_parsed("check-chars", &matches), ignore_case: matches.opt_present("ignore-case"), + zero_terminated: matches.opt_present("zero-terminated"), }; uniq.print_uniq(&mut open_input_file(in_file_name), &mut open_output_file(out_file_name));