Implemment lookaheadreader with lookahead and commit api

The LookAheadReader api works similar to read but it has 2 methods,
lookahead: it will read 1 byte (with internal ftell) without modifying
the file's own ftell() and commit() which saves the current file ftell

LookAheadReader can wrap both buffers and files
This commit is contained in:
oddcoder
2020-06-03 13:34:09 +02:00
parent f068673adc
commit 14e011b72c
2 changed files with 101 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
use super::{fseek_locked, FILE, SEEK_SET, ftell_locked};
use crate::core_io::Read;
struct LookAheadBuffer {
buf: *const u8,
pos: isize,
look_ahead: isize,
}
impl LookAheadBuffer {
fn look_ahead(&mut self) -> Result<Option<u8>, i32> {
let byte = unsafe { *self.buf.offset(self.look_ahead) };
self.look_ahead += 1;
Ok(Some(byte))
}
fn commit(&mut self) {
self.pos = self.look_ahead;
}
}
impl From<*const u8> for LookAheadBuffer {
fn from(buff: *const u8) -> LookAheadBuffer {
LookAheadBuffer {
buf: buff,
pos: 0,
look_ahead: 0,
}
}
}
struct LookAheadFile<'a> {
f: &'a mut FILE,
look_ahead: i64,
}
impl <'a> LookAheadFile<'a> {
fn look_ahead(&mut self) -> Result<Option<u8>, i32> {
let buf = &mut [0];
let seek = unsafe{ ftell_locked(self.f)};
unsafe{fseek_locked(self.f, self.look_ahead, SEEK_SET)};
let ret = match self.f.read(buf) {
Ok(0) => Ok(None),
Ok(_) => Ok(Some(buf[0])),
Err(_) => Err(-1),
};
unsafe{fseek_locked(self.f, seek, SEEK_SET)};
self.look_ahead += 1;
ret
}
fn commit(&mut self) {
unsafe { fseek_locked(self.f, self.look_ahead, SEEK_SET) };
}
}
impl <'a> From<&'a mut FILE> for LookAheadFile<'a> {
fn from(f: &'a mut FILE) -> LookAheadFile<'a> {
let look_ahead = unsafe{ftell_locked(f)} as i64;
LookAheadFile{
f,
look_ahead,
}
}
}
enum LookAheadReaderEnum<'a> {
FILE(LookAheadFile<'a>),
// (buffer, location)
BUFFER(LookAheadBuffer),
}
pub struct LookAheadReader<'a>(LookAheadReaderEnum<'a>);
impl <'a> LookAheadReader<'a> {
pub fn lookahead1(&mut self) -> Result<Option<u8>, i32> {
match &mut self.0 {
LookAheadReaderEnum::FILE(f) => f.look_ahead(),
LookAheadReaderEnum::BUFFER(b) => b.look_ahead(),
}
}
pub fn commit(&mut self) {
match &mut self.0 {
LookAheadReaderEnum::FILE(f) => f.commit(),
LookAheadReaderEnum::BUFFER(b) => b.commit(),
}
}
}
impl <'a> From<&'a mut FILE> for LookAheadReader<'a> {
fn from(f: &'a mut FILE) -> LookAheadReader {
LookAheadReader(LookAheadReaderEnum::FILE(f.into()))
}
}
impl <'a> From<*const u8> for LookAheadReader<'a > {
fn from(buff: *const u8) -> LookAheadReader<'a> {
LookAheadReader(LookAheadReaderEnum::BUFFER(buff.into()))
}
}
+1
View File
@@ -39,6 +39,7 @@ mod getdelim;
mod ext;
mod helpers;
mod lookaheadreader;
mod printf;
mod scanf;