template_cp/iom.rs
1//! # Input and output manager
2
3use std::{io, str};
4
5/// Scanner is a struct that can be used to parse input from a reader.
6///
7/// # Examples
8/// ```
9/// use cp_template::Scanner;
10/// use std::io;
11///
12/// fn main() {
13/// let mut scan = Scanner::new(io::stdin().lock());
14/// let mut out = io::BufWriter::new(io::stdout().lock());
15/// solve(&mut scan, &mut out);
16/// }
17///
18/// fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
19/// let n: usize = scan.tok();
20/// let v: Vec<i32> = (0..n).map(|_| scan.tok()).collect();
21/// writeln!(out, "{} {v:?}", n).ok();
22/// }
23/// ```
24/// ```
25/// use cp_template::Scanner;
26/// use std::io;
27///
28/// fn main() {
29/// let mut scan = read_file("in.txt").unwrap();
30/// let mut out = writer_file("out.txt").unwrap();
31/// solve(&mut scan, &mut out);
32/// }
33///
34/// fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
35/// let n: usize = scan.tok();
36/// let v: Vec<i32> = (0..n).map(|_| scan.tok()).collect();
37/// writeln!(out, "{} {v:?}", n).ok();
38/// }
39/// ```
40pub struct Scanner<R> {
41 reader: R,
42 buf_str: Vec<u8>,
43 buf_iter: str::SplitAsciiWhitespace<'static>,
44}
45
46impl<R: io::BufRead> Scanner<R> {
47 /// Creates a new Scanner.
48 /// # Examples
49 /// ```
50 /// use cp_template::Scanner;
51 ///
52 /// let mut scan = Scanner::new(std::io::stdin().lock());
53 /// ```
54 /// ```
55 /// use cp_template::Scanner;
56 ///
57 /// let file = std::fs::File::open(filename)?;
58 /// Scanner::new(io::BufReader::new(file))
59 /// ```
60 pub fn new(reader: R) -> Self {
61 Self {
62 reader,
63 buf_str: vec![],
64 buf_iter: "".split_ascii_whitespace(),
65 }
66 }
67
68 /// Reads a token.
69 /// # Panics
70 /// Panics if the token can't be parsed or the input is empty.
71 /// # Examples
72 /// ```
73 /// use cp_template::Scanner;
74 ///
75 /// let mut scan = Scanner::new(std::io::stdin().lock());
76 /// let n: i32 = scan.tok();
77 /// ```
78 /// ```
79 /// use cp_template::Scanner;
80 ///
81 /// let mut scan = Scanner::new(std::io::stdin().lock());
82 /// let n = scan.tok::<i32>();
83 /// ```
84 pub fn tok<T: str::FromStr>(&mut self) -> T {
85 loop {
86 if let Some(token) = self.buf_iter.next() {
87 return token.parse().ok().expect("Failed parse");
88 }
89 self.buf_str.clear();
90 self.reader
91 .read_until(b'\n', &mut self.buf_str)
92 .expect("Failed read");
93 self.buf_iter = unsafe {
94 let slice = str::from_utf8_unchecked(&self.buf_str);
95 std::mem::transmute(slice.split_ascii_whitespace())
96 }
97 }
98 }
99}
100
101/// Creates a Scanner from a file
102/// # Examples
103/// ```
104/// use template_cp::file_reader;
105///
106/// let mut scan = file_reader("in.txt").unwrap();
107/// let n: i32 = scan.tok();
108/// ```
109pub fn file_reader(filename: &str) -> io::Result<Scanner<io::BufReader<std::fs::File>>> {
110 let file = std::fs::File::open(filename)?;
111 Ok(Scanner::new(io::BufReader::new(file)))
112}
113
114/// Creates a BufWriter from a file
115/// # Examples
116/// ```
117/// use template_cp::file_writer;
118///
119/// let n = 42;
120/// let mut out = file_writer("out.txt").unwrap();
121/// writeln!(out, "{}", n).ok();
122/// ```
123pub fn file_writer(filename: &str) -> io::Result<io::BufWriter<std::fs::File>> {
124 let file = std::fs::File::create(filename)?;
125 Ok(io::BufWriter::new(file))
126}