Skip to content

Commit 1b1ab55

Browse files
authored
Merge pull request #243 from gcanat/wc2
Improve wc
2 parents f955da9 + 4d61894 commit 1b1ab55

File tree

1 file changed

+26
-27
lines changed

1 file changed

+26
-27
lines changed

text/wc.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct CountInfo {
4242
words: usize,
4343
chars: usize,
4444
nl: usize,
45+
was_space: bool,
4546
}
4647

4748
impl CountInfo {
@@ -50,6 +51,7 @@ impl CountInfo {
5051
words: 0,
5152
chars: 0,
5253
nl: 0,
54+
was_space: true,
5355
}
5456
}
5557

@@ -60,6 +62,19 @@ impl CountInfo {
6062
}
6163
}
6264

65+
const fn create_table() -> [bool; 256] {
66+
let mut table = [false; 256];
67+
table[9] = true;
68+
table[10] = true;
69+
table[11] = true;
70+
table[12] = true;
71+
table[13] = true;
72+
table[32] = true;
73+
table
74+
}
75+
76+
const BYTE_TABLE: [bool; 256] = create_table();
77+
6378
fn build_display_str(args: &Args, count: &CountInfo, filename: &OsStr) -> String {
6479
let mut output = String::with_capacity(filename.len() + (3 * 10));
6580

@@ -109,11 +124,11 @@ fn build_display_str(args: &Args, count: &CountInfo, filename: &OsStr) -> String
109124
output
110125
}
111126

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

115130
let mut buffer = [0; plib::BUFSZ];
116-
let mut in_word = false;
131+
let mut was_space = count.was_space;
117132

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

128143
for ch_u8 in bufslice {
129-
let ch = *ch_u8 as char;
130-
131-
if ch == '\n' {
132-
count.nl = count.nl + 1;
133-
if in_word {
134-
in_word = false;
135-
count.words = count.words + 1;
136-
}
137-
} else if ch.is_whitespace() {
138-
if in_word {
139-
in_word = false;
140-
count.words = count.words + 1;
141-
}
142-
} else {
143-
if !in_word {
144-
in_word = true;
145-
}
146-
}
144+
let is_space = table[*ch_u8 as usize];
145+
count.nl += (ch_u8 == &10) as usize;
146+
count.words += (!is_space && was_space) as usize;
147+
was_space = is_space;
147148
}
148149
}
149-
150-
if in_word {
151-
count.words = count.words + 1;
152-
}
150+
count.was_space = was_space;
153151

154152
Ok(())
155153
}
@@ -196,11 +194,12 @@ fn wc_file(
196194
chars_mode: bool,
197195
pathname: &PathBuf,
198196
count: &mut CountInfo,
197+
table: &[bool; 256],
199198
) -> io::Result<()> {
200199
if chars_mode {
201200
wc_file_chars(args, count, pathname)?;
202201
} else {
203-
wc_file_bytes(count, pathname)?;
202+
wc_file_bytes(count, pathname, table)?;
204203
}
205204

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

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

250-
if let Err(e) = wc_file(&args, chars_mode, filename, &mut count) {
249+
if let Err(e) = wc_file(&args, chars_mode, filename, &mut count, &BYTE_TABLE) {
251250
exit_code = 1;
252251
eprintln!("{}: {}", filename.display(), e);
253252
}

0 commit comments

Comments
 (0)