diff --git a/src/header/wchar/lookaheadreader.rs b/src/header/wchar/lookaheadreader.rs index ddf36a63f5..91157d771e 100644 --- a/src/header/wchar/lookaheadreader.rs +++ b/src/header/wchar/lookaheadreader.rs @@ -8,6 +8,7 @@ struct LookAheadBuffer { pos: isize, look_ahead: isize, } + impl LookAheadBuffer { fn look_ahead(&mut self) -> Result, i32> { let wchar = unsafe { *self.buf.offset(self.look_ahead) }; @@ -34,20 +35,72 @@ impl From<*const wint_t> for LookAheadBuffer { } } -pub struct LookAheadReader(LookAheadBuffer); +struct LookAheadFile<'a> { + f: &'a mut FILE, + look_ahead: i64, +} -impl LookAheadReader { +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 as off_t, 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; + + // TODO: This is a 8 bit char, wee need to read a wchar + ret.map(|c| c.map(wint_t::from)) + } + + fn commit(&mut self) { + unsafe { fseek_locked(self.f, self.look_ahead as off_t, 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(LookAheadBuffer); +pub struct LookAheadReader<'a>(LookAheadReaderEnum<'a>); + +impl LookAheadReader<'_> { pub fn lookahead1(&mut self) -> Result, i32> { - self.0.look_ahead() + match &mut self.0 { + LookAheadReaderEnum::FILE(f) => f.look_ahead(), + LookAheadReaderEnum::BUFFER(b) => b.look_ahead(), + } } - pub fn commit(&mut self) { - self.0.commit() + match &mut self.0 { + LookAheadReaderEnum::FILE(f) => f.commit(), + LookAheadReaderEnum::BUFFER(b) => b.commit(), + } } } -impl From<*const wint_t> for LookAheadReader { - fn from(buff: *const wint_t) -> LookAheadReader { - LookAheadReader(buff.into()) +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 wint_t> for LookAheadReader<'a> { + fn from(buff: *const wint_t) -> LookAheadReader<'a> { + LookAheadReader(LookAheadReaderEnum::BUFFER(buff.into())) } } diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index ff3102aa25..3d277241ec 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -10,6 +10,7 @@ use crate::{ stdlib::{malloc, MB_CUR_MAX, MB_LEN_MAX}, string, time::*, + wchar::lookaheadreader::LookAheadReader, wctype::*, }, iter::{NulTerminated, NulTerminatedInclusive}, @@ -1006,9 +1007,16 @@ pub unsafe extern "C" fn wmemset(ws: *mut wchar_t, wc: wchar_t, n: size_t) -> *m ws } -// #[no_mangle] -pub extern "C" fn wscanf(format: *const wchar_t, ap: va_list) -> c_int { - unimplemented!(); +#[no_mangle] +pub unsafe extern "C" fn wscanf(format: *const wchar_t, ap: va_list) -> c_int { + let mut file = (*stdin).lock(); + if let Err(_) = file.try_set_byte_orientation_unlocked() { + return -1; + } + + let f: &mut FILE = &mut *file; + let reader: LookAheadReader = f.into(); + wscanf::scanf(reader, format, ap) } #[no_mangle] diff --git a/tests/wchar/wscanf.c b/tests/wchar/wscanf.c index c74c4ded86..6d362cc472 100644 --- a/tests/wchar/wscanf.c +++ b/tests/wchar/wscanf.c @@ -92,5 +92,9 @@ int main () wprintf(L"%d \"%s\" \"%s\" \"%s\" \"%s\"\n", ret, &protobuf, &slashbuf, &hostbuf, &pathbuf); + // wchar_t str [80]; + // wprintf(L"Enter your family name: "); + // wscanf(L"%ls",str); + return 0; }