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
74pub 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
140pub 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
224pub 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
273pub 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#[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}