From 14e011b72c3af286e28132da8d067a15bfcff327 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Wed, 3 Jun 2020 13:34:09 +0200 Subject: [PATCH] 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 --- src/header/stdio/lookaheadreader.rs | 100 ++++++++++++++++++++++++++++ src/header/stdio/mod.rs | 1 + 2 files changed, 101 insertions(+) create mode 100644 src/header/stdio/lookaheadreader.rs diff --git a/src/header/stdio/lookaheadreader.rs b/src/header/stdio/lookaheadreader.rs new file mode 100644 index 0000000000..5c08d86751 --- /dev/null +++ b/src/header/stdio/lookaheadreader.rs @@ -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, 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, 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, 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())) + } +} diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 8273f6deab..f9ab3551e3 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -39,6 +39,7 @@ mod getdelim; mod ext; mod helpers; +mod lookaheadreader; mod printf; mod scanf;