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