@@ -42,6 +42,7 @@ struct CountInfo {
4242 words : usize ,
4343 chars : usize ,
4444 nl : usize ,
45+ was_space : bool ,
4546}
4647
4748impl 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+
6378fn 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