1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 20:47:46 +00:00

Merge pull request #749 from jbcrail/refactor-tail-2

tail: use read_line/read instead of lines/bytes
This commit is contained in:
Michael Gehring 2015-12-19 08:43:43 +01:00
commit bc0dd2006c

View file

@ -248,56 +248,83 @@ fn obsolete(options: &[String]) -> (Vec<String>, Option<usize>) {
(options, None) (options, None)
} }
macro_rules! tail_impl ( fn tail<T: Read>(reader: &mut BufReader<T>, settings: &Settings) {
($kind:ty, $kindfn:ident, $kindprint:ident, $reader:ident, $count:expr, $beginning:expr) => ({ // Read through each line/char and store them in a ringbuffer that always
// read through each line and store them in a ringbuffer that always contains // contains count lines/chars. When reaching the end of file, output the
// count lines/chars. When reaching the end of file, output the data in the // data in the ringbuf.
// ringbuf. match settings.mode {
let mut count = $count; FilterMode::Lines(mut count) => {
let mut ringbuf: VecDeque<$kind> = VecDeque::new(); let mut ringbuf: VecDeque<String> = VecDeque::new();
let data = $reader.$kindfn().skip( let mut skip = if settings.beginning {
if $beginning {
let temp = count; let temp = count;
count = ::std::usize::MAX; count = ::std::usize::MAX;
temp - 1 temp - 1
} else { } else {
0 0
} };
); loop {
for io_datum in data { let mut datum = String::new();
match io_datum { match reader.read_line(&mut datum) {
Ok(datum) => { Ok(0) => break,
if count <= ringbuf.len() { Ok(_) => {
ringbuf.pop_front(); if skip > 0 {
} skip -= 1;
ringbuf.push_back(datum); } else {
if count <= ringbuf.len() {
ringbuf.pop_front();
}
ringbuf.push_back(datum);
}
},
Err(err) => panic!(err)
} }
Err(err) => panic!(err)
} }
} let mut stdout = stdout();
let mut stdout = stdout(); for datum in ringbuf.iter() {
for datum in ringbuf.iter() { print_string(&mut stdout, datum);
$kindprint(&mut stdout, datum); }
}
})
);
fn tail<T: Read>(reader: &mut BufReader<T>, settings: &Settings) {
match settings.mode {
FilterMode::Lines(count) => {
tail_impl!(String, lines, print_string, reader, count, settings.beginning)
}, },
FilterMode::Bytes(count) => { FilterMode::Bytes(mut count) => {
tail_impl!(u8, bytes, print_byte, reader, count, settings.beginning) let mut ringbuf: VecDeque<u8> = VecDeque::new();
let mut skip = if settings.beginning {
let temp = count;
count = ::std::usize::MAX;
temp - 1
} else {
0
};
loop {
let mut datum = [0; 1];
match reader.read(&mut datum) {
Ok(0) => break,
Ok(_) => {
if skip > 0 {
skip -= 1;
} else {
if count <= ringbuf.len() {
ringbuf.pop_front();
}
ringbuf.push_back(datum[0]);
}
},
Err(err) => panic!(err)
}
}
let mut stdout = stdout();
for datum in ringbuf.iter() {
print_byte(&mut stdout, datum);
}
} }
} }
// if we follow the file, sleep a bit and print the rest if the file has grown. // if we follow the file, sleep a bit and print the rest if the file has grown.
while settings.follow { while settings.follow {
sleep(Duration::new(0, settings.sleep_msec*1000)); sleep(Duration::new(0, settings.sleep_msec*1000));
for io_line in reader.lines() { loop {
match io_line { let mut datum = String::new();
Ok(line) => print!("{}", line), match reader.read_line(&mut datum) {
Ok(0) => break,
Ok(_) => print!("{}", datum),
Err(err) => panic!(err) Err(err) => panic!(err)
} }
} }