mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 05:27:45 +00:00
wc: count_fast optimization using seek
This commit is contained in:
parent
253926f2e2
commit
6186153a08
2 changed files with 15 additions and 2 deletions
|
@ -10,7 +10,7 @@ use super::WordCountable;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{self, ErrorKind, Read};
|
use std::io::{self, ErrorKind, Read, Seek, SeekFrom};
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use libc::{sysconf, S_IFREG, _SC_PAGESIZE};
|
use libc::{sysconf, S_IFREG, _SC_PAGESIZE};
|
||||||
|
@ -100,7 +100,7 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> (usize, Opti
|
||||||
// would count up only to a couple of bytes.
|
// would count up only to a couple of bytes.
|
||||||
// This condition usually occurs for files in pseudo-filesystems like /proc, /sys
|
// This condition usually occurs for files in pseudo-filesystems like /proc, /sys
|
||||||
// that report `st_size` in the multiples of system page size.
|
// that report `st_size` in the multiples of system page size.
|
||||||
// In such cases - fall back on full read
|
// In such cases - attempt `seek()` for the end of file
|
||||||
//
|
//
|
||||||
// And finally a special case of input redirection in *nix shell:
|
// And finally a special case of input redirection in *nix shell:
|
||||||
// `( wc -c ; wc -c ) < file` should return
|
// `( wc -c ; wc -c ) < file` should return
|
||||||
|
@ -126,6 +126,10 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> (usize, Opti
|
||||||
// regular file or file from /proc, /sys and similar pseudo-filesystems
|
// regular file or file from /proc, /sys and similar pseudo-filesystems
|
||||||
// with size that is NOT a multiple of system page size
|
// with size that is NOT a multiple of system page size
|
||||||
return (stat.st_size as usize, None);
|
return (stat.st_size as usize, None);
|
||||||
|
} else if let Some(file) = handle.inner_file() {
|
||||||
|
if let Ok(n) = file.seek(SeekFrom::End(0)) {
|
||||||
|
return (n as usize, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
|
|
@ -17,12 +17,14 @@ use std::os::unix::io::AsRawFd;
|
||||||
pub trait WordCountable: AsRawFd + Read {
|
pub trait WordCountable: AsRawFd + Read {
|
||||||
type Buffered: BufRead;
|
type Buffered: BufRead;
|
||||||
fn buffered(self) -> Self::Buffered;
|
fn buffered(self) -> Self::Buffered;
|
||||||
|
fn inner_file(&mut self) -> Option<&mut File>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
pub trait WordCountable: Read {
|
pub trait WordCountable: Read {
|
||||||
type Buffered: BufRead;
|
type Buffered: BufRead;
|
||||||
fn buffered(self) -> Self::Buffered;
|
fn buffered(self) -> Self::Buffered;
|
||||||
|
fn inner_file(&mut self) -> Option<&mut File>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WordCountable for StdinLock<'_> {
|
impl WordCountable for StdinLock<'_> {
|
||||||
|
@ -31,6 +33,9 @@ impl WordCountable for StdinLock<'_> {
|
||||||
fn buffered(self) -> Self::Buffered {
|
fn buffered(self) -> Self::Buffered {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
fn inner_file(&mut self) -> Option<&mut File> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WordCountable for File {
|
impl WordCountable for File {
|
||||||
|
@ -39,4 +44,8 @@ impl WordCountable for File {
|
||||||
fn buffered(self) -> Self::Buffered {
|
fn buffered(self) -> Self::Buffered {
|
||||||
BufReader::new(self)
|
BufReader::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inner_file(&mut self) -> Option<&mut File> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue