@@ -17,11 +17,9 @@ use nom::{
1717} ;
1818use std:: {
1919 char,
20- collections:: { HashMap , HashSet } ,
2120 error:: Error ,
2221 fmt:: { Debug , Display } ,
2322 io:: { BufRead , Write } ,
24- ops:: Not ,
2523} ;
2624use uucore:: error:: { FromIo , UError , UResult } ;
2725use uucore:: translate;
@@ -583,42 +581,58 @@ impl<A: SymbolTranslator, B: SymbolTranslator> SymbolTranslator for ChainedSymbo
583581 }
584582}
585583
584+ /// Convert a set of bytes to a 256-element bitmap for O(1) lookup
585+ fn set_to_bitmap ( set : & [ u8 ] ) -> [ bool ; 256 ] {
586+ let mut bitmap = [ false ; 256 ] ;
587+ for & byte in set {
588+ bitmap[ byte as usize ] = true ;
589+ }
590+ bitmap
591+ }
592+
586593#[ derive( Debug ) ]
587594pub struct DeleteOperation {
588- set : Vec < u8 > ,
595+ delete_table : [ bool ; 256 ] ,
589596}
590597
591598impl DeleteOperation {
592599 pub fn new ( set : Vec < u8 > ) -> Self {
593- Self { set }
600+ Self {
601+ delete_table : set_to_bitmap ( & set) ,
602+ }
594603 }
595604}
596605
597606impl SymbolTranslator for DeleteOperation {
598607 fn translate ( & mut self , current : u8 ) -> Option < u8 > {
599- // keep if not present in the set
600- self . set . contains ( & current) . not ( ) . then_some ( current)
608+ // keep if not present in the delete set
609+ ( ! self . delete_table [ current as usize ] ) . then_some ( current)
601610 }
602611}
603612
604613#[ derive( Debug ) ]
605614pub struct TranslateOperation {
606- translation_map : HashMap < u8 , u8 > ,
615+ translation_table : [ u8 ; 256 ] ,
607616}
608617
609618impl TranslateOperation {
610619 pub fn new ( set1 : Vec < u8 > , set2 : Vec < u8 > ) -> Result < Self , BadSequence > {
620+ // Initialize translation table with identity mapping
621+ let mut translation_table = std:: array:: from_fn ( |i| i as u8 ) ;
622+
611623 if let Some ( fallback) = set2. last ( ) . copied ( ) {
612- Ok ( Self {
613- translation_map : set1
614- . into_iter ( )
615- . zip ( set2. into_iter ( ) . chain ( std:: iter:: repeat ( fallback) ) )
616- . collect :: < HashMap < _ , _ > > ( ) ,
617- } )
624+ // Apply translations from set1 to set2
625+ for ( from, to) in set1
626+ . into_iter ( )
627+ . zip ( set2. into_iter ( ) . chain ( std:: iter:: repeat ( fallback) ) )
628+ {
629+ translation_table[ from as usize ] = to;
630+ }
631+
632+ Ok ( Self { translation_table } )
618633 } else if set1. is_empty ( ) && set2. is_empty ( ) {
619- Ok ( Self {
620- translation_map : HashMap :: new ( ) ,
621- } )
634+ // Identity mapping for empty sets
635+ Ok ( Self { translation_table } )
622636 } else {
623637 Err ( BadSequence :: EmptySet2WhenNotTruncatingSet1 )
624638 }
@@ -627,33 +641,28 @@ impl TranslateOperation {
627641
628642impl SymbolTranslator for TranslateOperation {
629643 fn translate ( & mut self , current : u8 ) -> Option < u8 > {
630- Some (
631- self . translation_map
632- . get ( & current)
633- . copied ( )
634- . unwrap_or ( current) ,
635- )
644+ Some ( self . translation_table [ current as usize ] )
636645 }
637646}
638647
639648#[ derive( Debug , Clone ) ]
640649pub struct SqueezeOperation {
641- set1 : HashSet < u8 > ,
650+ squeeze_table : [ bool ; 256 ] ,
642651 previous : Option < u8 > ,
643652}
644653
645654impl SqueezeOperation {
646655 pub fn new ( set1 : Vec < u8 > ) -> Self {
647656 Self {
648- set1 : set1 . into_iter ( ) . collect ( ) ,
657+ squeeze_table : set_to_bitmap ( & set1 ) ,
649658 previous : None ,
650659 }
651660 }
652661}
653662
654663impl SymbolTranslator for SqueezeOperation {
655664 fn translate ( & mut self , current : u8 ) -> Option < u8 > {
656- let next = if self . set1 . contains ( & current) {
665+ let next = if self . squeeze_table [ current as usize ] {
657666 match self . previous {
658667 Some ( v) if v == current => None ,
659668 _ => Some ( current) ,
@@ -672,19 +681,26 @@ where
672681 R : BufRead ,
673682 W : Write ,
674683{
675- let mut buf = [ 0 ; 8192 ] ;
676- let mut output_buf = Vec :: new ( ) ;
684+ const BUFFER_SIZE : usize = 32768 ; // Large buffer for better throughput
685+ let mut buf = [ 0 ; BUFFER_SIZE ] ;
686+ let mut output_buf = Vec :: with_capacity ( buf. len ( ) ) ;
687+
688+ loop {
689+ let length = match input. read ( & mut buf[ ..] ) {
690+ Ok ( 0 ) => break , // EOF reached
691+ Ok ( len) => len,
692+ Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: Interrupted => continue ,
693+ Err ( e) => return Err ( e. map_err_context ( || translate ! ( "tr-error-read-error" ) ) ) ,
694+ } ;
677695
678- while let Ok ( length) = input. read ( & mut buf[ ..] ) {
679- if length == 0 {
680- break ; // EOF reached
696+ // Process the buffer and collect translated chars to output
697+ output_buf. clear ( ) ;
698+ for & byte in & buf[ ..length] {
699+ if let Some ( translated) = translator. translate ( byte) {
700+ output_buf. push ( translated) ;
701+ }
681702 }
682703
683- let filtered = buf[ ..length]
684- . iter ( )
685- . filter_map ( |& c| translator. translate ( c) ) ;
686- output_buf. extend ( filtered) ;
687-
688704 #[ cfg( not( target_os = "windows" ) ) ]
689705 output
690706 . write_all ( & output_buf)
@@ -699,8 +715,6 @@ where
699715 return Err ( err. map_err_context ( || translate ! ( "tr-error-write-error" ) ) ) ;
700716 }
701717 }
702-
703- output_buf. clear ( ) ;
704718 }
705719
706720 Ok ( ( ) )
0 commit comments