alt_std/
io.rs

1use core::*;
2use core::fmt::{Arguments, Write};
3use crate::string::*;
4use crate::ctypes::*;
5use crate::stream::*;
6
7#[link(name = "c")]
8extern "C"
9{
10	pub static mut stdin: *mut libc::FILE;
11
12	pub static mut stdout: *mut libc::FILE;
13
14    pub static mut stderr: *mut libc::FILE;
15}
16
17pub fn fprintStrings<'a>(f: *mut libc::FILE, arr: &[&'a str]) {
18    for s in arr {
19        unsafe { libc::fprintf(f,"%.*s\0".as_bytes().as_ptr() as *const i8, s.len(), s.as_bytes().as_ptr())};
20    }
21}
22
23pub fn format(args: Arguments<'_>) -> String {
24    let mut output = String::new();
25    output.write_fmt(args).expect("a formatting trait implementation returned an error");
26    output
27}
28
29#[macro_export]
30macro_rules! format {
31    ($fmt:expr, $($args:expr),+) => {
32        $crate::io::format(format_args!($fmt, $($args),+))
33    };
34}
35
36#[macro_export]
37macro_rules! fprint {
38    () => {{}};
39    ($stream:expr, $arg:expr) => { fprint!($stream, "{}", $arg) };
40    ($stream:expr, $($args:expr),+) => { unsafe { $crate::io::fprintStrings($stream, &[format!($($args),+).toStr()]) } };
41}
42
43#[macro_export]
44macro_rules! fprintln {
45    () => {};
46    ($stream:expr, $arg:expr) => { fprintln!($stream, "{}", $arg) };
47    ($stream:expr, $($args:expr),+) => { unsafe { $crate::io::fprintStrings($stream, &[format!($($args),+).toStr(), "\n"]) } };
48}
49
50#[macro_export]
51macro_rules! print {
52    () => {};
53    ($($args:expr),+) => { fprint!($crate::io::stdout, $($args),+) };
54}
55
56#[macro_export]
57macro_rules! println {
58    () => {};
59    ($($args:expr),+) => { fprintln!($crate::io::stdout, $($args),+) };
60}
61
62#[macro_export]
63macro_rules! error {
64    () => {};
65    ($($args:expr),+) => { fprint!($crate::io::stderr, $($args),+) };
66}
67
68#[macro_export]
69macro_rules! errorln {
70    () => {};
71    ($($args:expr),+) => { fprintln!($crate::io::stderr, $($args),+) };
72}
73
74////////////////////////////////////////////////////////////////////////////////
75pub struct FileWriter {
76    file    : *mut ::libc::FILE,
77}
78
79impl FileWriter {
80    pub fn create(fname: &str) -> Result<Self, ()> {
81        let mut sname = String::from(fname);
82        sname.add('\0' as u8);
83        let f = unsafe { ::libc::fopen(sname.toStr().as_bytes().as_ptr() as *const i8, "wb\0".as_bytes().as_ptr() as *const i8) };
84        if f as * const _ == ::core::ptr::null() {
85            Result::Err(())
86        } else {
87            Result::Ok(Self { file: f })
88        }
89    }
90
91    pub fn write(&mut self, bytes: &[u8]) -> Result<usize, ()> {
92        let count = unsafe {  ::libc::fwrite(bytes.as_ptr() as *const c_void, 1, bytes.len(), self.file) };
93        if count < bytes.len() {
94            if unsafe { ::libc::ferror(self.file) } != 0 {
95                Result::Err(())
96            } else {
97                Result::Ok(count)
98            }
99        } else {
100            Result::Ok(count)
101        }
102    }
103
104    pub fn tell(&self) -> usize { unsafe { ::libc::ftell(self.file) as usize } }
105    pub fn size(&self) -> usize {
106        unsafe {
107            let curr = self.tell();
108            ::libc::fseek(self.file, 0, ::libc::SEEK_END);
109            let size = self.tell();
110            ::libc::fseek(self.file, curr as i64, ::libc::SEEK_SET);
111            size
112        }
113    }
114}
115
116impl Drop for FileWriter {
117    fn drop(&mut self) {
118        unsafe { ::libc::fclose(self.file) };
119    }
120}
121
122impl Stream for FileWriter {
123    fn tell(&self) -> usize { self.tell() }
124    fn size(&self) -> usize { self.size() }
125}
126
127impl StreamSeek for FileWriter {
128    fn seek(&mut self, pos: usize) -> Result<usize, ()> {
129        unsafe { ::libc::fseek(self.file, pos as i64, ::libc::SEEK_SET) };
130        Result::Ok(self.tell())
131    }
132}
133
134impl StreamWriter for FileWriter {
135    fn write(&mut self, buff: &[u8]) -> Result<usize, ()> {
136        self.write(buff)
137    }
138}
139
140////////////////////////////////////////////////////////////////////////////////
141pub struct FileReader {
142    file    : *mut ::libc::FILE,
143}
144
145impl FileReader {
146    pub fn open(fname: &str) -> Result<Self, ()> {
147        let mut sname = String::from(fname);
148        sname.add(b'\0');
149        let f = unsafe { ::libc::fopen(sname.toStr().as_bytes().as_ptr() as *const i8, "rb\0".as_bytes().as_ptr() as *const i8) };
150        if f as * const _ == ::core::ptr::null() {
151            Result::Err(())
152        } else {
153            Result::Ok(Self { file: f })
154        }
155    }
156
157    pub fn tell(&self) -> usize { unsafe { ::libc::ftell(self.file) as usize } }
158    pub fn size(&self) -> usize {
159        unsafe {
160            let curr = self.tell();
161            ::libc::fseek(self.file, 0, ::libc::SEEK_END);
162            let size = self.tell();
163            ::libc::fseek(self.file, curr as i64, ::libc::SEEK_SET);
164            size
165        }
166    }
167
168    pub fn read(&mut self, buff: &mut [u8]) -> Result<usize, ()> {
169        let count = unsafe {  ::libc::fread(buff.as_mut_ptr() as *mut c_void, 1, buff.len(), self.file) };
170        if count < buff.len() {
171            if unsafe { ::libc::ferror(self.file) } != 0 {
172                Result::Err(())
173            } else {
174                Result::Ok(count)
175            }
176        } else {
177            Result::Ok(count)
178        }
179    }
180
181    pub fn readLine(&mut self, buff: &mut [u8]) -> Result<usize, ()> {
182        let n = unsafe { ::libc::fgets(buff.as_mut_ptr() as *mut i8, buff.len() as c_int, self.file) };
183        Result::Ok(n as usize)
184    }
185}
186
187
188impl Drop for FileReader {
189    fn drop(&mut self) {
190        unsafe { ::libc::fclose(self.file) };
191    }
192}
193
194impl Stream for FileReader {
195    fn tell(&self) -> usize { self.tell() }
196    fn size(&self) -> usize { self.size() }
197}
198
199impl StreamSeek for FileReader {
200    fn seek(&mut self, pos: usize) -> Result<usize, ()> {
201        unsafe { ::libc::fseek(self.file, pos as i64, ::libc::SEEK_SET) };
202        Result::Ok(self.tell())
203    }
204}
205
206impl StreamReader for FileReader {
207    fn read(&mut self, buff: &mut [u8]) -> Result<usize, ()> {
208        self.read(buff)
209    }
210
211    fn isEOF(&self) -> bool {
212        if unsafe { ::libc::feof(self.file) } != 0 {
213            true
214        } else {
215            false
216        }
217    }
218}
219
220pub trait StreamSeek : Stream {
221    fn seek(&mut self, cursor: usize) -> Result<usize, ()>;
222}
223
224////////////////////////////////////////////////////////////////////////////////
225pub struct File {}
226
227impl File {
228    pub fn exist(fname: &str) -> bool {
229        let f = FileReader::open(fname);
230        match f {
231            Ok(_) => true,
232            _ => false,
233        }
234    }
235
236    pub fn remove(fname: &str) -> Result<(), ()> {
237        let mut sname = String::from(fname);
238        sname.add(b'\0');
239        let f = unsafe { ::libc::remove(sname.toStr().as_bytes().as_ptr() as *const i8) };
240        if f != 0 {
241            Err(())
242        } else {
243            Ok(())
244        }
245    }
246
247    pub fn rename(oldName: &str, newName: &str) -> Result<(), ()> {
248        let mut o = String::from(oldName);
249        o.add(b'\0');
250        let mut n = String::from(newName);
251        n.add(b'\0');
252        let f = unsafe { ::libc::rename(o.toStr().as_bytes().as_ptr() as *const i8, n.toStr().as_bytes().as_ptr() as *const i8) };
253        if f != 0 {
254            Err(())
255        } else {
256            Ok(())
257        }
258    }
259
260    pub fn tmpname() -> String {
261        unsafe {
262            let s = crate::mem::allocArray::<i8>(::libc::L_tmpnam as usize);
263            ::libc::tmpnam(s);
264            let len = ::libc::strlen(s);
265            let slice = ::core::slice::from_raw_parts(s as *const u8, len);
266            let st = String::from(&::core::str::from_utf8(slice).unwrap());
267            crate::mem::free(s);
268            st
269        }
270    }
271}
272
273////////////////////////////////////////////////////////////////////////////////
274pub mod console {
275    pub fn readLine(s: &mut [u8]) -> usize {
276        unsafe { ::libc::strlen(::libc::fgets(s.as_mut_ptr() as *mut i8, s.len() as super::c_int, super::stdin)) as usize }
277    }
278}
279
280////////////////////////////////////////////////////////////////////////////////
281
282#[cfg(test)]
283mod tests {
284    use super::*;
285    #[test]
286    fn testCreateReadRemoveFile() {
287        let name = File::tmpname();
288        {
289            let mut f = FileWriter::create(name.toStr());
290            let s = "Hello File";
291            match &mut f {
292                Ok(f) => {
293                    let res = f.write(s.as_bytes());
294                    assert!(res.unwrap() == s.as_bytes().len());
295                    assert!(File::exist(name.toStr()));
296                },
297                _ => panic!("couldn't create file!")
298            }
299        }
300
301        {
302            let mut f = FileReader::open(name.toStr());
303            let s = "Hello File";
304            match &mut f {
305                Ok(f) => {
306                    assert!(f.size() == 10);
307                    let mut buff : [u8; 10] = [0; 10];
308                    let res = f.read(&mut buff);
309                    assert!(res.unwrap() == s.as_bytes().len());
310                    assert!(str::from_utf8(&buff).unwrap() == s);
311                },
312                _ => panic!("couldn't open file!")
313            }
314        }
315
316        {
317            File::remove(name.toStr()).unwrap();
318        }
319    }
320}