Skip to content

Commit

Permalink
change output type
Browse files Browse the repository at this point in the history
  • Loading branch information
bminaiev committed Dec 28, 2023
1 parent 1291f64 commit 05d14c6
Show file tree
Hide file tree
Showing 15 changed files with 66 additions and 148 deletions.
5 changes: 5 additions & 0 deletions algo_lib/src/io/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ impl Input {
}
}

pub fn new_stdin() -> Self {
let stdin = std::io::stdin();
Self::new(Box::new(stdin))
}

pub fn new_file<P: AsRef<Path>>(path: P) -> Self {
let file = std::fs::File::open(&path)
.unwrap_or_else(|_| panic!("Can't open file: {:?}", path.as_ref().as_os_str()));
Expand Down
82 changes: 16 additions & 66 deletions algo_lib/src/io/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ impl Output {
}
}

pub fn new_stdout() -> Self {
let stdout = std::io::stdout();
Self::new(Box::new(stdout))
}

pub fn new_file(path: impl AsRef<std::path::Path>) -> Self {
let file = std::fs::File::create(path).unwrap();
Self::new(Box::new(file))
}

pub fn new_with_auto_flush(output: Box<dyn Write>) -> Self {
Self {
output,
Expand All @@ -36,10 +46,15 @@ impl Output {
}
}

pub fn print<T: Writable>(&mut self, s: &T) {
pub fn print<T: Writable>(&mut self, s: T) {
s.write(self);
}

pub fn println<T: Writable>(&mut self, s: T) {
s.write(self);
self.put(b'\n');
}

pub fn put(&mut self, b: u8) {
self.buf[self.at] = b;
self.at += 1;
Expand Down Expand Up @@ -188,68 +203,3 @@ impl<T: Writable, U: Writable, V: Writable> Writable for (T, U, V) {
self.2.write(output);
}
}

pub static mut OUTPUT: Option<Output> = None;

pub fn set_global_output_to_stdout() {
unsafe {
OUTPUT = Some(Output::new(Box::new(std::io::stdout())));
}
}

pub fn set_global_output_to_file(path: &str) {
unsafe {
let out_file =
std::fs::File::create(path).unwrap_or_else(|_| panic!("Can't create file {}", path));
OUTPUT = Some(Output::new(Box::new(out_file)));
}
}

pub fn set_global_output_to_none() {
unsafe {
match &mut OUTPUT {
None => {}
Some(output) => output.flush(),
}
OUTPUT = None;
}
}

pub fn output() -> &'static mut Output {
unsafe {
match &mut OUTPUT {
None => {
panic!("Global output wasn't initialized");
}
Some(output) => output,
}
}
}

#[macro_export]
macro_rules! out {
($first: expr $(,$args:expr )*) => {
output().print(&$first);
$(output().put(b' ');
output().print(&$args);
)*
output().maybe_flush();
}
}

#[macro_export]
macro_rules! out_line {
($first: expr $(, $args:expr )* ) => {
{
out!($first $(,$args)*);
output().put(b'\n');
output().maybe_flush();
}
};
() => {
{
output().put(b'\n');
output().maybe_flush();
}
};
}
10 changes: 4 additions & 6 deletions algo_lib/src/io/task_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use std::io::Write;

use super::{
input::Input,
output::{Output, OUTPUT},
output::Output,
task_io_settings::{TaskIoSettings, TaskIoType},
};

pub fn run_task<Res>(io: TaskIoSettings, run: impl FnOnce(Input) -> Res) -> Res {
pub fn run_task<Res>(io: TaskIoSettings, run: impl FnOnce(Input, Output) -> Res) -> Res {
let output: Box<dyn Write> = match io.output {
TaskIoType::Std => Box::new(std::io::stdout()),
TaskIoType::File(file) => {
Expand All @@ -15,9 +15,7 @@ pub fn run_task<Res>(io: TaskIoSettings, run: impl FnOnce(Input) -> Res) -> Res
}
};

unsafe {
OUTPUT = Some(Output::new(output));
}
let output = Output::new(output);

let input = match io.input {
TaskIoType::Std => {
Expand All @@ -27,5 +25,5 @@ pub fn run_task<Res>(io: TaskIoSettings, run: impl FnOnce(Input) -> Res) -> Res
TaskIoType::File(file) => Input::new_file(file),
};

run(input)
run(input, output)
}
4 changes: 2 additions & 2 deletions templates/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//$JSON

use algo_lib::io::input::Input;
use algo_lib::io::output::output;
use algo_lib::io::output::Output;
#[allow(unused)]
use algo_lib::{out, out_line, dbg};
use algo_lib::dbg;

$SOLVE

Expand Down
7 changes: 2 additions & 5 deletions templates/main/file_out.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
let output: Box<dyn std::io::Write> = Box::new(std::fs::File::create("$OUT_FILE").unwrap());

unsafe {
algo_lib::io::output::OUTPUT = Some(algo_lib::io::output::Output::new(output));
}
let output: Box<dyn std::io::Write> = Box::new(std::fs::File::create().unwrap());
let mut output = algo_lib::io::output::Output::new_file(output);
2 changes: 1 addition & 1 deletion templates/main/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
$INPUT
$OUTPUT
crate::solution::run(input);
crate::solution::run(input, &mut output);
}
2 changes: 1 addition & 1 deletion templates/main/stdin.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
let input = algo_lib::io::input::Input::new(Box::new(std::io::stdin()));
let input = algo_lib::io::input::Input::new_stdin();
6 changes: 1 addition & 5 deletions templates/main/stdout.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
let output: Box<dyn std::io::Write> = Box::new(std::io::stdout());

unsafe {
algo_lib::io::output::OUTPUT = Some(algo_lib::io::output::Output::new(output));
}
let mut output = algo_lib::io::output::Output::new_stdout();
8 changes: 4 additions & 4 deletions templates/multi_eof.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
let mut i = 1usize;
while input.peek().is_some() {
solve(&mut input, i);
i += 1;
}
while input.peek().is_some() {
solve(&mut input, &mut output, i);
i += 1;
}
6 changes: 3 additions & 3 deletions templates/multi_number.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let t = input.read();
for i in 0usize..t {
solve(&mut input, i + 1);
}
for i in 0usize..t {
solve(&mut input, &mut output, i + 1);
}
2 changes: 1 addition & 1 deletion templates/single.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
solve(&mut input, 1);
solve(&mut input, &mut output, 1);
9 changes: 0 additions & 9 deletions templates/sites/atcoder.rs

This file was deleted.

6 changes: 3 additions & 3 deletions templates/sites/default.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
fn solve(input: &mut Input, _test_case: usize) {
fn solve(input: &mut Input, output: &mut Output, _test_case: usize) {
$CARET
}

pub(crate) fn run(mut input: Input) -> bool {
pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
$INVOKE
output().flush();
output.flush();
true
}
13 changes: 0 additions & 13 deletions templates/sites/google.rs

This file was deleted.

52 changes: 23 additions & 29 deletions templates/tester.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::io::Cursor;
use std::io::{Cursor, Write};
use std::path::Path;
use std::sync::mpsc::Sender;
use std::time::Instant;

use algo_lib::io::input::Input;
use algo_lib::io::last_changed_file::find_last_changed_file;
use algo_lib::io::output::{
set_global_output_to_file, set_global_output_to_stdout, Output, OUTPUT,
};
use algo_lib::io::output::Output;

const EPS: f64 = 1e-9;

Expand Down Expand Up @@ -56,15 +55,13 @@ fn check(expected: &mut &[u8], actual: &mut &[u8]) -> Result<(), String> {
Ok(())
}

static mut OUT: Vec<u8> = Vec::new();

struct WriteDelegate {}
struct WriteDelegate {
snd: Sender<Vec<u8>>,
}

impl std::io::Write for WriteDelegate {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
unsafe {
OUT.append(&mut Vec::from(buf));
}
self.snd.send(buf.to_vec()).unwrap();
Ok(buf.len())
}

Expand Down Expand Up @@ -102,22 +99,21 @@ pub(crate) fn run_single_test(name: &str) -> bool {
}
println!("{}Output:{}", BLUE, DEF);
match std::panic::catch_unwind(|| {
unsafe {
OUT.clear();
}
let input = Input::new_file(path);
let (snd, rcv) = std::sync::mpsc::channel();
let out: Box<dyn Write> = Box::new(WriteDelegate { snd });

let mut output = Output::new(out);
let started = std::time::Instant::now();
unsafe {
OUTPUT = Some(Output::new(Box::new(WriteDelegate {})));
let is_exhausted = crate::run(input, &mut output);
drop(output);
let mut out_vec = Vec::new();
while let Ok(buf) = rcv.recv() {
out_vec.extend(buf);
}
let is_exhausted = crate::run(input);
let res = started.elapsed();
let output;
unsafe {
output = OUT.clone();
}
println!("{}", String::from_utf8_lossy(&output));
(output, res, is_exhausted)
println!("{}", String::from_utf8_lossy(&out_vec));
(out_vec, res, is_exhausted)
}) {
Ok((output, duration, is_exhausted)) => {
println!(
Expand Down Expand Up @@ -211,17 +207,16 @@ pub(crate) fn run_tests() -> bool {

#[allow(unused)]
pub fn run_locally() {
let sin = std::io::stdin();
let input = Input::new(Box::new(sin));
set_global_output_to_stdout();
crate::run(input);
let input = Input::new_stdin();
let mut output = Output::new_stdout();
crate::run(input, &mut output);
}

#[allow(unused)]
pub fn run_with_specific_file<P: AsRef<Path>>(input_file: P) {
let input = Input::new_file(input_file);
set_global_output_to_file("output.txt");
crate::run(input);
let mut output = Output::new_file("output.txt");
crate::run(input, &mut output);
}

#[allow(unused)]
Expand All @@ -245,7 +240,6 @@ pub fn run_with_last_downloaded_file() {

#[allow(unused)]
pub fn run_stress(stress: fn() -> ()) {
set_global_output_to_stdout();
let start = Instant::now();
stress();
eprintln!("Finished in {}ms", start.elapsed().as_millis());
Expand Down

0 comments on commit 05d14c6

Please sign in to comment.