Skip to content

Commit

Permalink
Merge pull request #243 from gcanat/wc2
Browse files Browse the repository at this point in the history
Improve wc
  • Loading branch information
jgarzik authored Sep 23, 2024
2 parents f955da9 + 4d61894 commit 1b1ab55
Showing 1 changed file with 26 additions and 27 deletions.
53 changes: 26 additions & 27 deletions text/wc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct CountInfo {
words: usize,
chars: usize,
nl: usize,
was_space: bool,
}

impl CountInfo {
Expand All @@ -50,6 +51,7 @@ impl CountInfo {
words: 0,
chars: 0,
nl: 0,
was_space: true,
}
}

Expand All @@ -60,6 +62,19 @@ impl CountInfo {
}
}

const fn create_table() -> [bool; 256] {
let mut table = [false; 256];
table[9] = true;
table[10] = true;
table[11] = true;
table[12] = true;
table[13] = true;
table[32] = true;
table
}

const BYTE_TABLE: [bool; 256] = create_table();

fn build_display_str(args: &Args, count: &CountInfo, filename: &OsStr) -> String {
let mut output = String::with_capacity(filename.len() + (3 * 10));

Expand Down Expand Up @@ -109,11 +124,11 @@ fn build_display_str(args: &Args, count: &CountInfo, filename: &OsStr) -> String
output
}

fn wc_file_bytes(count: &mut CountInfo, pathname: &PathBuf) -> io::Result<()> {
fn wc_file_bytes(count: &mut CountInfo, pathname: &PathBuf, table: &[bool; 256]) -> io::Result<()> {
let mut file = plib::io::input_stream(pathname, false)?;

let mut buffer = [0; plib::BUFSZ];
let mut in_word = false;
let mut was_space = count.was_space;

loop {
let n_read = file.read(&mut buffer[..])?;
Expand All @@ -126,30 +141,13 @@ fn wc_file_bytes(count: &mut CountInfo, pathname: &PathBuf) -> io::Result<()> {
let bufslice = &buffer[0..n_read];

for ch_u8 in bufslice {
let ch = *ch_u8 as char;

if ch == '\n' {
count.nl = count.nl + 1;
if in_word {
in_word = false;
count.words = count.words + 1;
}
} else if ch.is_whitespace() {
if in_word {
in_word = false;
count.words = count.words + 1;
}
} else {
if !in_word {
in_word = true;
}
}
let is_space = table[*ch_u8 as usize];
count.nl += (ch_u8 == &10) as usize;
count.words += (!is_space && was_space) as usize;
was_space = is_space;
}
}

if in_word {
count.words = count.words + 1;
}
count.was_space = was_space;

Ok(())
}
Expand Down Expand Up @@ -196,11 +194,12 @@ fn wc_file(
chars_mode: bool,
pathname: &PathBuf,
count: &mut CountInfo,
table: &[bool; 256],
) -> io::Result<()> {
if chars_mode {
wc_file_chars(args, count, pathname)?;
} else {
wc_file_bytes(count, pathname)?;
wc_file_bytes(count, pathname, table)?;
}

let output = build_display_str(args, count, pathname.as_os_str());
Expand Down Expand Up @@ -237,7 +236,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if args.files.is_empty() {
let mut count = CountInfo::new();

if let Err(e) = wc_file(&args, chars_mode, &PathBuf::new(), &mut count) {
if let Err(e) = wc_file(&args, chars_mode, &PathBuf::new(), &mut count, &BYTE_TABLE) {
exit_code = 1;
eprintln!("stdin: {}", e);
}
Expand All @@ -247,7 +246,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
for filename in &args.files {
let mut count = CountInfo::new();

if let Err(e) = wc_file(&args, chars_mode, filename, &mut count) {
if let Err(e) = wc_file(&args, chars_mode, filename, &mut count, &BYTE_TABLE) {
exit_code = 1;
eprintln!("{}: {}", filename.display(), e);
}
Expand Down

0 comments on commit 1b1ab55

Please sign in to comment.