@@ -42,6 +42,7 @@ struct CountInfo {
42
42
words : usize ,
43
43
chars : usize ,
44
44
nl : usize ,
45
+ was_space : bool ,
45
46
}
46
47
47
48
impl CountInfo {
@@ -50,6 +51,7 @@ impl CountInfo {
50
51
words : 0 ,
51
52
chars : 0 ,
52
53
nl : 0 ,
54
+ was_space : true ,
53
55
}
54
56
}
55
57
@@ -60,6 +62,19 @@ impl CountInfo {
60
62
}
61
63
}
62
64
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
+
63
78
fn build_display_str ( args : & Args , count : & CountInfo , filename : & OsStr ) -> String {
64
79
let mut output = String :: with_capacity ( filename. len ( ) + ( 3 * 10 ) ) ;
65
80
@@ -109,11 +124,11 @@ fn build_display_str(args: &Args, count: &CountInfo, filename: &OsStr) -> String
109
124
output
110
125
}
111
126
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 < ( ) > {
113
128
let mut file = plib:: io:: input_stream ( pathname, false ) ?;
114
129
115
130
let mut buffer = [ 0 ; plib:: BUFSZ ] ;
116
- let mut in_word = false ;
131
+ let mut was_space = count . was_space ;
117
132
118
133
loop {
119
134
let n_read = file. read ( & mut buffer[ ..] ) ?;
@@ -126,30 +141,13 @@ fn wc_file_bytes(count: &mut CountInfo, pathname: &PathBuf) -> io::Result<()> {
126
141
let bufslice = & buffer[ 0 ..n_read] ;
127
142
128
143
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;
147
148
}
148
149
}
149
-
150
- if in_word {
151
- count. words = count. words + 1 ;
152
- }
150
+ count. was_space = was_space;
153
151
154
152
Ok ( ( ) )
155
153
}
@@ -196,11 +194,12 @@ fn wc_file(
196
194
chars_mode : bool ,
197
195
pathname : & PathBuf ,
198
196
count : & mut CountInfo ,
197
+ table : & [ bool ; 256 ] ,
199
198
) -> io:: Result < ( ) > {
200
199
if chars_mode {
201
200
wc_file_chars ( args, count, pathname) ?;
202
201
} else {
203
- wc_file_bytes ( count, pathname) ?;
202
+ wc_file_bytes ( count, pathname, table ) ?;
204
203
}
205
204
206
205
let output = build_display_str ( args, count, pathname. as_os_str ( ) ) ;
@@ -237,7 +236,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
237
236
if args. files . is_empty ( ) {
238
237
let mut count = CountInfo :: new ( ) ;
239
238
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 ) {
241
240
exit_code = 1 ;
242
241
eprintln ! ( "stdin: {}" , e) ;
243
242
}
@@ -247,7 +246,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
247
246
for filename in & args. files {
248
247
let mut count = CountInfo :: new ( ) ;
249
248
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 ) {
251
250
exit_code = 1 ;
252
251
eprintln ! ( "{}: {}" , filename. display( ) , e) ;
253
252
}
0 commit comments