haar_lib/io/
fastio.rs

1//! 高速な標準入出力
2#![allow(clippy::new_without_default)]
3
4use std::fmt::Display;
5use std::io::{Read, Write};
6
7/// 高速な標準入出力
8pub struct FastIO {
9    in_bytes: Vec<u8>,
10    in_cur: usize,
11    out_buf: std::io::BufWriter<std::io::Stdout>,
12}
13
14impl FastIO {
15    /// [`FastIO`]を生成する。
16    pub fn new() -> Self {
17        let mut s = vec![];
18        std::io::stdin().read_to_end(&mut s).unwrap();
19
20        let cout = std::io::stdout();
21
22        Self {
23            in_bytes: s,
24            in_cur: 0,
25            out_buf: std::io::BufWriter::new(cout),
26        }
27    }
28
29    /// 1バイトだけ読み出す。
30    #[inline]
31    pub fn getc(&mut self) -> Option<u8> {
32        let c = *self.in_bytes.get(self.in_cur)?;
33        self.in_cur += 1;
34        Some(c)
35    }
36
37    /// 1バイトだけ先読みする。
38    #[inline]
39    pub fn peek(&self) -> Option<u8> {
40        Some(*self.in_bytes.get(self.in_cur)?)
41    }
42
43    /// `is_ascii_whitespace`が`true`である間を読み飛ばす。
44    #[inline]
45    pub fn skip(&mut self) {
46        while self.peek().is_some_and(|c| c.is_ascii_whitespace()) {
47            self.in_cur += 1;
48        }
49    }
50
51    /// [`u64`]型の数値を読み出す。
52    pub fn read_u64(&mut self) -> u64 {
53        self.skip();
54        let mut ret: u64 = 0;
55
56        while self.peek().is_some_and(|c| c.is_ascii_digit()) {
57            ret = ret * 10 + (self.in_bytes[self.in_cur] - b'0') as u64;
58            self.in_cur += 1;
59        }
60
61        ret
62    }
63
64    /// [`u32`]型の数値を読み出す。
65    pub fn read_u32(&mut self) -> u32 {
66        self.read_u64() as u32
67    }
68
69    /// [`usize`]型の数値を読み出す。
70    pub fn read_usize(&mut self) -> usize {
71        self.read_u64() as usize
72    }
73
74    /// [`i64`]型の数値を読み出す。
75    pub fn read_i64(&mut self) -> i64 {
76        self.skip();
77        let mut ret: i64 = 0;
78
79        let minus = if self.peek() == Some(b'-') {
80            self.in_cur += 1;
81            true
82        } else {
83            false
84        };
85
86        while self.peek().is_some_and(|c| c.is_ascii_digit()) {
87            ret = ret * 10 + (self.in_bytes[self.in_cur] - b'0') as i64;
88            self.in_cur += 1;
89        }
90
91        if minus {
92            ret = -ret;
93        }
94
95        ret
96    }
97
98    /// [`i32`]型の数値を読み出す。
99    pub fn read_i32(&mut self) -> i32 {
100        self.read_i64() as i32
101    }
102
103    /// [`isize`]型の数値を読み出す。
104    pub fn read_isize(&mut self) -> isize {
105        self.read_i64() as isize
106    }
107
108    /// [`f64`]型の数値を読み出す。
109    pub fn read_f64(&mut self) -> f64 {
110        self.read_chars()
111            .into_iter()
112            .collect::<String>()
113            .parse()
114            .unwrap()
115    }
116
117    /// 文字列を[`Vec<char>`]として読み出す。
118    pub fn read_chars(&mut self) -> Vec<char> {
119        self.read_bytes().into_iter().map(Into::into).collect()
120    }
121
122    /// 文字列を[`String`]として読み出す。
123    pub fn read_string(&mut self) -> String {
124        self.read_chars().into_iter().collect()
125    }
126
127    /// 文字列を[`Vec<u8>`]として読み出す。
128    pub fn read_bytes(&mut self) -> Vec<u8> {
129        self.skip();
130        let mut ret = vec![];
131
132        while self.peek().is_some_and(|c| c.is_ascii_graphic()) {
133            ret.push(self.in_bytes[self.in_cur]);
134            self.in_cur += 1;
135        }
136
137        ret
138    }
139
140    /// `is_ascii_whitespace`でない文字を一文字だけ読み出す。
141    pub fn read_char(&mut self) -> char {
142        self.skip();
143        self.getc().unwrap().into()
144    }
145
146    /// `s`を標準出力に書き込む。
147    pub fn write<T: Display>(&mut self, s: T) {
148        self.out_buf.write_all(s.to_string().as_bytes()).unwrap();
149    }
150
151    /// `s`を標準出力に**逆順**に書き込む。
152    pub fn write_rev<T: Display>(&mut self, s: T) {
153        let mut s = s.to_string().as_bytes().to_vec();
154        s.reverse();
155        self.out_buf.write_all(&s).unwrap();
156    }
157
158    /// `s`と改行文字を標準出力に書き込む。
159    pub fn writeln<T: Display>(&mut self, s: T) {
160        self.write(s);
161        self.out_buf.write_all(b"\n").unwrap();
162    }
163
164    /// `s`の**逆順**と改行文字を標準出力に書き込む。
165    pub fn writeln_rev<T: Display>(&mut self, s: T) {
166        self.write_rev(s);
167        self.out_buf.write_all(b"\n").unwrap();
168    }
169}
170
171impl Drop for FastIO {
172    fn drop(&mut self) {
173        self.out_buf.flush().unwrap();
174    }
175}