io_synesthesist/
macros.rs

1// @adjivas - github.com/adjivas. See the LICENSE
2// file at the top-level directory of this distribution and at
3// https://github.com/adjivas/io
4//
5// This file may not be copied, modified, or distributed
6// except according to those terms.
7
8/// The `write` macro writes to output the text
9/// and returns the Some 0i32 or None according to success.
10
11#[macro_export]
12macro_rules! write {
13    ($text: expr) => ({
14        let mut result: bool = false;
15
16        for len in 0i32..std::i32::MAX {
17            if unsafe {
18                *$text.offset(len as isize)
19            } == 0u8 {
20                result = write!($text, len);
21                break ;
22            }
23        }
24        result
25    });
26    ($text: expr, $len: expr) => ({
27        write!($text, $len, 1)
28    });
29    ($text: expr, $len: expr, $out: expr) => ({
30        extern crate io_synesthesist as io;
31        match unsafe {
32            io::ffi::write (
33                $out as i32,
34                $text as *const i8,
35                $len as i32,
36            )
37        } {
38          -1 => false,
39          _ => true,
40        }
41    });
42}
43
44/// The `writeln` macro writes to output the text with a breakline
45/// and returns the Some 0i32 or None according to success.
46
47#[macro_export]
48macro_rules! writeln {
49    ($text: expr) => ({
50        write!($text) && write!("\n".as_ptr(), 1)
51    });
52    ($text: expr, $len: expr) => ({
53        write!($text, $len) && write!("\n".as_ptr(), 1)
54    });
55    ($text: expr, $len: expr, $out: expr) => ({
56        write!($text, $len, $out) && write!("\n".as_ptr(), 1)
57    });
58}
59
60/// The `write_number` macro writes to output the number
61/// and returns the Some 0i32 or None according to success.
62
63#[macro_export]
64#[cfg(not(feature = "synesthesia"))]
65macro_rules! write_number {
66    ($number: expr) => ({
67        write_number!($number, 1)
68    });
69    ($number: expr, $out: expr) => ({
70        let mut decimal = $number;
71        let mut buf: [u8; 64] = [0; 64];
72        let mut result: bool = false;
73
74        for target in (0..64).rev() {
75            buf[target] = {decimal % 10 + 48} as u8;
76            decimal /= 10;
77            if decimal == 0 {
78                result = write! (
79                    buf.as_ptr().offset (
80                        target as isize
81                    ),
82                    64 - target,
83                    $out
84                );
85                break ;
86            }
87        }
88        result
89    });
90}
91
92#[macro_export]
93#[cfg(feature = "synesthesia")]
94macro_rules! write_number {
95    ($number: expr) => ({
96        write_number!($number, 1)
97    });
98    ($number: expr, $out: expr) => ({
99        let mut decimal = $number;
100        let mut buf: [u8; 384] = [0; 384]; // 64*6
101        let mut result: bool = false;
102
103        for target in {0i32..{384}}.rev().filter(|&x| x % 6 == 0) {
104            let digit: u8 = {decimal % 10 + 48} as u8;
105
106            buf[{target-5} as usize] = b'\x1B';
107            buf[{target-4} as usize] = b'[';
108            buf[{target-3} as usize] = b'3';
109            buf[{target-2} as usize] = digit;
110            buf[{target-1} as usize] = b'm';
111            buf[{target-0} as usize] = digit;
112            decimal /= 10;
113            if decimal == 0 {
114                result = write! (
115                    buf.as_ptr().offset (
116                        {target-5} as isize
117                    ),
118                    384 - target,
119                    $out
120                );
121                break ;
122            }
123        }
124        result && writeln!("\x1B[0m".as_ptr(), 4)
125    });
126}
127
128/// The `writeln_number` macro writes to output the number with a breakline
129/// and returns the Some 0i32 or None according to success.
130
131#[macro_export]
132macro_rules! writeln_number {
133    ($number: expr) => ({
134        writeln_number!($number, 1)
135    });
136    ($number: expr, $out: expr) => ({
137        write_number!($number, $out) && write!("\n".as_ptr(), 1)
138    });
139}
140
141/// The `write_character` macro writes to output the character
142/// and returns the Some 0i32 or None according to success.
143
144#[macro_export]
145macro_rules! write_character {
146    ($character: expr) => ({
147        write_character!($character, 1)
148    });
149    ($character: expr, $out: expr) => ({
150        write!([$character].as_ptr(), 1, $out)
151    });
152}
153
154/// The `write_character` macro writes to output the character with a breakline
155/// and returns the Some 0i32 or None according to success.
156
157#[macro_export]
158macro_rules! writeln_character {
159    ($character: expr) => ({
160        writeln_character!($character, 1)
161    });
162    ($character: expr, $out: expr) => ({
163        write!([$character].as_ptr(), 1, $out) && write!("\n".as_ptr(), $out)
164    });
165}
166
167/// The `write_error` macro writes to output the error
168/// and returns the Some 0i32 or None according to success.
169
170#[macro_export]
171#[cfg(not(feature = "synesthesia"))]
172macro_rules! write_err {
173    ($text: expr) => ({
174        let mut result: bool = false;
175
176        for len in 0i32..std::i32::MAX {
177            if unsafe {
178                *$text.offset(len as isize)
179            } == 0u8 {
180                result = write_err!($text, len);
181                break ;
182            }
183        }
184        result
185    });
186    ($text: expr, $len: expr) => ({
187        write!($text, $len, 2)
188    });
189}
190
191#[macro_export]
192#[cfg(feature = "synesthesia")]
193macro_rules! write_err {
194    ($text: expr) => ({
195        let mut result: bool = false;
196
197        for len in 0i32..std::i32::MAX {
198            if unsafe {
199                *$text.offset(len as isize)
200            } == 0u8 {
201                result = writeln!("\x1B[31m".as_ptr(), 5)
202                      && write_err!($text, len);
203                break ;
204            }
205        }
206        result && writeln!("\x1B[0m".as_ptr(), 4)
207    });
208    ($text: expr, $len: expr) => ({
209        writeln!("\x1B[31m".as_ptr(), 5) &&
210        write!($text, $len, 2) &&
211        writeln!("\x1B[0m".as_ptr(), 4)
212    });
213}
214
215/// The `writeln_error` macro writes to output the error
216/// and returns the Some 0i32 or None according to success.
217
218#[macro_export]
219macro_rules! writeln_err {
220    ($text: expr) => ({
221        write_err!($text) && write!("\n".as_ptr(), 1, 2)
222    });
223}
224
225/// The `read` macro reads the input and returns None
226/// or the Some of thetuple (len, text).
227
228#[macro_export]
229macro_rules! read {
230    () => ({
231        read!(io::ffi::BUFF)
232    });
233    ($len: expr) => ({
234        read!($len, 0)
235    });
236    ($len: expr, $ins: expr) => ({
237        extern crate io_synesthesist as io;
238        let line: [i8; io::ffi::BUFF] = [0; io::ffi::BUFF];
239
240        match unsafe {
241          io::ffi::read (
242            $ins as i32,
243            line.as_ptr() as *mut i8,
244            $len as i32,
245          )
246        } {
247          -1 => None,
248          ret => Some((ret, line)),
249        }
250    });
251}
252
253
254/// The `read_character` macro reads and
255/// returns one character.
256
257#[macro_export]
258macro_rules! read_character {
259    () => ({
260        match read!(1) {
261            Some((_, c)) => Some(c[0]),
262            None => None,
263        }
264    });
265}
266
267/// The `read_number` macro reads and
268/// returns the number.
269
270#[macro_export]
271macro_rules! read_number {
272    () => ({
273        match {
274            read_character!()
275        } {
276            Some(45) => Some(-read_number!(0i8)),
277            Some(d @ 48...57) => Some(read_number!(d - 48i8)),
278            _ => None ,
279        }
280    });
281    ($start: expr) => ({
282        extern crate io_synesthesist as io;
283        read_number!($start, io::ffi::BUFF_READ_NUMBER)
284    });
285    ($start: expr, $limit: expr) => ({
286        fn result (
287            acc: i64,
288            lim: usize
289        ) -> i64 {
290            match {
291                (read_character!(), lim)
292            } {
293                (Some(d @ 48...57), lim) if lim != 0 => result (
294                    {acc * 10i64} + {d - 48i8} as i64,
295                    lim - 1
296                ),
297                _ => acc,
298            }
299        }
300        result($start as i64, $limit)
301    });
302}
303
304/// The `read_command` macro reads and
305/// returns the concat of all letter.
306
307#[macro_export]
308macro_rules! read_command {
309    () => ({
310        match {
311            read_character!()
312        } {
313            Some(47) => read_command!(0u64),
314            _ => None ,
315        }
316    });
317    ($start: expr) => ({
318        extern crate io_synesthesist as io;
319        read_command!($start, io::ffi::BUFF_READ_COMMAND)
320    });
321    ($start: expr, $limit: expr) => ({
322        fn result (
323            acc: u64,
324            lim: usize
325        ) -> Option<u64> {
326            match {
327                (read_character!(), lim)
328            } {
329                (Some(d @  65...90), lim) if lim != 0 => {
330                    result(10 + acc * 100 + {d - 65i8} as u64, lim -1)
331                },
332                (Some(d @  97...122), lim) if lim != 0 => {
333                    result(10 + acc * 100 + {d - 97i8} as u64, lim -1)
334                },
335                _ => Some(acc),
336            }
337        }
338        result($start as u64, $limit)
339    });
340}
341
342/// The `ioctl` macro reads the input and
343/// returns None or a tuple (len, text).
344
345#[macro_export]
346macro_rules! ioctl {
347    () => ({
348        extern crate io_synesthesist as io;
349        let mut term = Box::new(io::ffi::Termios {
350            c_iflag: 0,
351            c_oflag: 0,
352            c_cflag: 0,
353            c_lflag: 0,
354            c_line: 0,
355            c_cc: [0; io::ffi::NCCS],
356            c_ispeed: 0,
357            c_ospeed: 0,
358        });
359
360        ioctl!(io::ffi::TermiosControl::GETA, &mut *term);
361        term
362
363    });
364    ($control: expr) => ({
365        let mut term = ioctl!();
366
367        term.c_lflag = $control;
368        term
369    });
370    ($req: expr, $term: expr) => ({
371        extern crate io_synesthesist as io;
372        unsafe {
373            io::ffi::ioctl (
374                io::ffi::STDIN_FILENO,
375                $req as u64,
376                $term,
377           )
378        }
379    });
380}