mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
split: add forwards_thru_file() helper function
Add helper function `forwards_thru_file()` that finds the index in a reader of the byte immediately following the `n`th instance of a given byte.
This commit is contained in:
parent
8c298e97a5
commit
d27d6bc32c
1 changed files with 106 additions and 0 deletions
|
@ -386,6 +386,83 @@ fn follow<T: BufRead>(readers: &mut [(T, &String)], settings: &Settings) -> URes
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the index after the given number of instances of a given byte.
|
||||||
|
///
|
||||||
|
/// This function reads through a given reader until `num_delimiters`
|
||||||
|
/// instances of `delimiter` have been seen, returning the index of
|
||||||
|
/// the byte immediately following that delimiter. If there are fewer
|
||||||
|
/// than `num_delimiters` instances of `delimiter`, this returns the
|
||||||
|
/// total number of bytes read from the `reader` until EOF.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// This function returns an error if there is an error during reading
|
||||||
|
/// from `reader`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// use std::io::Cursor;
|
||||||
|
///
|
||||||
|
/// let mut reader = Cursor::new("a\nb\nc\nd\ne\n");
|
||||||
|
/// let i = forwards_thru_file(&mut reader, 2, b'\n').unwrap();
|
||||||
|
/// assert_eq!(i, 4);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If `num_delimiters` is zero, then this function always returns
|
||||||
|
/// zero:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// use std::io::Cursor;
|
||||||
|
///
|
||||||
|
/// let mut reader = Cursor::new("a\n");
|
||||||
|
/// let i = forwards_thru_file(&mut reader, 0, b'\n').unwrap();
|
||||||
|
/// assert_eq!(i, 0);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If there are fewer than `num_delimiters` instances of `delimiter`
|
||||||
|
/// in the reader, then this function returns the total number of
|
||||||
|
/// bytes read:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// use std::io::Cursor;
|
||||||
|
///
|
||||||
|
/// let mut reader = Cursor::new("a\n");
|
||||||
|
/// let i = forwards_thru_file(&mut reader, 2, b'\n').unwrap();
|
||||||
|
/// assert_eq!(i, 2);
|
||||||
|
/// ```
|
||||||
|
fn forwards_thru_file<R>(
|
||||||
|
reader: &mut R,
|
||||||
|
num_delimiters: usize,
|
||||||
|
delimiter: u8,
|
||||||
|
) -> std::io::Result<usize>
|
||||||
|
where
|
||||||
|
R: Read,
|
||||||
|
{
|
||||||
|
let mut reader = BufReader::new(reader);
|
||||||
|
|
||||||
|
let mut buf = vec![];
|
||||||
|
let mut total = 0;
|
||||||
|
for _ in 0..num_delimiters {
|
||||||
|
match reader.read_until(delimiter, &mut buf) {
|
||||||
|
Ok(0) => {
|
||||||
|
return Ok(total);
|
||||||
|
}
|
||||||
|
Ok(n) => {
|
||||||
|
total += n;
|
||||||
|
buf.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(total)
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterate over bytes in the file, in reverse, until we find the
|
/// Iterate over bytes in the file, in reverse, until we find the
|
||||||
/// `num_delimiters` instance of `delimiter`. The `file` is left seek'd to the
|
/// `num_delimiters` instance of `delimiter`. The `file` is left seek'd to the
|
||||||
/// position just after that delimiter.
|
/// position just after that delimiter.
|
||||||
|
@ -534,3 +611,32 @@ fn get_block_size(md: &Metadata) -> u64 {
|
||||||
md.len()
|
md.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use crate::forwards_thru_file;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_forwards_thru_file_zero() {
|
||||||
|
let mut reader = Cursor::new("a\n");
|
||||||
|
let i = forwards_thru_file(&mut reader, 0, b'\n').unwrap();
|
||||||
|
assert_eq!(i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_forwards_thru_file_basic() {
|
||||||
|
// 01 23 45 67 89
|
||||||
|
let mut reader = Cursor::new("a\nb\nc\nd\ne\n");
|
||||||
|
let i = forwards_thru_file(&mut reader, 2, b'\n').unwrap();
|
||||||
|
assert_eq!(i, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_forwards_thru_file_past_end() {
|
||||||
|
let mut reader = Cursor::new("x\n");
|
||||||
|
let i = forwards_thru_file(&mut reader, 2, b'\n').unwrap();
|
||||||
|
assert_eq!(i, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue