xref: /relibc/src/header/stdio/lookaheadreader.rs (revision 041d1604b526a0b908d4222e39baa0030a94fd8f)
1 use super::{fseek_locked, ftell_locked, FILE, SEEK_SET};
2 use crate::{
3     core_io::Read,
4     platform::types::off_t,
5 };
6 struct LookAheadBuffer {
7     buf: *const u8,
8     pos: isize,
9     look_ahead: isize,
10 }
11 impl LookAheadBuffer {
12     fn look_ahead(&mut self) -> Result<Option<u8>, i32> {
13         let byte = unsafe { *self.buf.offset(self.look_ahead) };
14         if byte == 0 {
15             Ok(None)
16         } else {
17             self.look_ahead += 1;
18             Ok(Some(byte))
19         }
20     }
21 
22     fn commit(&mut self) {
23         self.pos = self.look_ahead;
24     }
25 }
26 
27 impl From<*const u8> for LookAheadBuffer {
28     fn from(buff: *const u8) -> LookAheadBuffer {
29         LookAheadBuffer {
30             buf: buff,
31             pos: 0,
32             look_ahead: 0,
33         }
34     }
35 }
36 
37 struct LookAheadFile<'a> {
38     f: &'a mut FILE,
39     look_ahead: i64,
40 }
41 
42 impl<'a> LookAheadFile<'a> {
43     fn look_ahead(&mut self) -> Result<Option<u8>, i32> {
44         let buf = &mut [0];
45         let seek = unsafe { ftell_locked(self.f) };
46         unsafe { fseek_locked(self.f, self.look_ahead as off_t, SEEK_SET) };
47         let ret = match self.f.read(buf) {
48             Ok(0) => Ok(None),
49             Ok(_) => Ok(Some(buf[0])),
50             Err(_) => Err(-1),
51         };
52         unsafe { fseek_locked(self.f, seek, SEEK_SET) };
53         self.look_ahead += 1;
54         ret
55     }
56 
57     fn commit(&mut self) {
58         unsafe { fseek_locked(self.f, self.look_ahead as off_t, SEEK_SET) };
59     }
60 }
61 
62 impl<'a> From<&'a mut FILE> for LookAheadFile<'a> {
63     fn from(f: &'a mut FILE) -> LookAheadFile<'a> {
64         let look_ahead = unsafe { ftell_locked(f) } as i64;
65         LookAheadFile { f, look_ahead }
66     }
67 }
68 
69 enum LookAheadReaderEnum<'a> {
70     FILE(LookAheadFile<'a>),
71     // (buffer, location)
72     BUFFER(LookAheadBuffer),
73 }
74 
75 pub struct LookAheadReader<'a>(LookAheadReaderEnum<'a>);
76 
77 impl<'a> LookAheadReader<'a> {
78     pub fn lookahead1(&mut self) -> Result<Option<u8>, i32> {
79         match &mut self.0 {
80             LookAheadReaderEnum::FILE(f) => f.look_ahead(),
81             LookAheadReaderEnum::BUFFER(b) => b.look_ahead(),
82         }
83     }
84     pub fn commit(&mut self) {
85         match &mut self.0 {
86             LookAheadReaderEnum::FILE(f) => f.commit(),
87             LookAheadReaderEnum::BUFFER(b) => b.commit(),
88         }
89     }
90 }
91 
92 impl<'a> From<&'a mut FILE> for LookAheadReader<'a> {
93     fn from(f: &'a mut FILE) -> LookAheadReader {
94         LookAheadReader(LookAheadReaderEnum::FILE(f.into()))
95     }
96 }
97 
98 impl<'a> From<*const u8> for LookAheadReader<'a> {
99     fn from(buff: *const u8) -> LookAheadReader<'a> {
100         LookAheadReader(LookAheadReaderEnum::BUFFER(buff.into()))
101     }
102 }
103