Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wc: specialize scanning loop on settings. #3708

Merged
merged 6 commits into from
Jul 18, 2022
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 79 additions & 25 deletions src/uu/wc/src/wc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,29 +306,83 @@ fn word_count_from_reader<T: WordCountable>(
mut reader: T,
settings: &Settings,
) -> (WordCount, Option<io::Error>) {
let only_count_bytes = settings.show_bytes
&& (!(settings.show_chars
|| settings.show_lines
|| settings.show_max_line_length
|| settings.show_words));
if only_count_bytes {
let (bytes, error) = count_bytes_fast(&mut reader);
return (
WordCount {
bytes,
..WordCount::default()
},
error,
);
}

// we do not need to decode the byte stream if we're only counting bytes/newlines
let decode_chars = settings.show_chars || settings.show_words || settings.show_max_line_length;

if !decode_chars {
return count_bytes_and_lines_fast(&mut reader);
match (
settings.show_bytes,
settings.show_chars,
settings.show_lines,
settings.show_max_line_length,
settings.show_words,
) {
(false, false, false, false, false) => (WordCount::default(), None),
resistor marked this conversation as resolved.
Show resolved Hide resolved
(true, false, false, false, false) => {
// Fast path when only show_bytes is true.
let (bytes, error) = count_bytes_fast(&mut reader);
(
WordCount {
bytes,
..WordCount::default()
},
error,
)
}
(false, false, true, false, false) | (true, false, true, false, false) => {
// Fast path when only (show_bytes || show_lines) is true.
count_bytes_and_lines_fast(&mut reader)
}
(_, false, false, false, true) => {
word_count_from_reader_specialized::<_, false, false, false, true>(reader)
}
(_, false, false, true, false) => {
word_count_from_reader_specialized::<_, false, false, true, false>(reader)
}
(_, false, false, true, true) => {
word_count_from_reader_specialized::<_, false, false, true, true>(reader)
resistor marked this conversation as resolved.
Show resolved Hide resolved
}
(_, false, true, false, true) => {
word_count_from_reader_specialized::<_, false, true, false, true>(reader)
}
(_, false, true, true, false) => {
word_count_from_reader_specialized::<_, false, true, true, false>(reader)
}
(_, false, true, true, true) => {
word_count_from_reader_specialized::<_, false, true, true, true>(reader)
}
(_, true, false, false, false) => {
word_count_from_reader_specialized::<_, true, false, false, false>(reader)
}
(_, true, false, false, true) => {
word_count_from_reader_specialized::<_, true, false, false, true>(reader)
}
(_, true, false, true, false) => {
word_count_from_reader_specialized::<_, true, false, true, false>(reader)
}
(_, true, false, true, true) => {
word_count_from_reader_specialized::<_, true, false, true, true>(reader)
}
(_, true, true, false, false) => {
word_count_from_reader_specialized::<_, true, true, false, false>(reader)
}
(_, true, true, false, true) => {
word_count_from_reader_specialized::<_, true, true, false, true>(reader)
}
(_, true, true, true, false) => {
word_count_from_reader_specialized::<_, true, true, true, false>(reader)
}
(_, true, true, true, true) => {
word_count_from_reader_specialized::<_, true, true, true, true>(reader)
}
}
}

fn word_count_from_reader_specialized<
T: WordCountable,
const SHOW_CHARS: bool,
const SHOW_LINES: bool,
const SHOW_MAX_LINE_LENGTH: bool,
const SHOW_WORDS: bool,
>(
reader: T,
) -> (WordCount, Option<io::Error>) {
let mut total = WordCount::default();
let mut reader = BufReadDecoder::new(reader.buffered());
let mut in_word = false;
Expand All @@ -338,7 +392,7 @@ fn word_count_from_reader<T: WordCountable>(
match chunk {
Ok(text) => {
for ch in text.chars() {
if settings.show_words {
if SHOW_WORDS {
if ch.is_whitespace() {
in_word = false;
} else if ch.is_ascii_control() {
Expand All @@ -348,7 +402,7 @@ fn word_count_from_reader<T: WordCountable>(
total.words += 1;
}
}
if settings.show_max_line_length {
if SHOW_MAX_LINE_LENGTH {
match ch {
'\n' | '\r' | '\x0c' => {
total.max_line_length = max(current_len, total.max_line_length);
Expand All @@ -363,10 +417,10 @@ fn word_count_from_reader<T: WordCountable>(
}
}
}
if settings.show_lines && ch == '\n' {
if SHOW_LINES && ch == '\n' {
total.lines += 1;
}
if settings.show_chars {
if SHOW_CHARS {
total.chars += 1;
}
}
Expand Down