Compare commits
2 Commits
d64bc6b9ed
...
c0d288e9e8
Author | SHA1 | Date |
---|---|---|
Johannes Kapfhammer | c0d288e9e8 | |
Johannes Kapfhammer | 080e3f1261 |
11
example.cpp
11
example.cpp
|
@ -27,6 +27,9 @@ signed main() {
|
|||
a.foo();
|
||||
a.bar(3,4,"hi");
|
||||
|
||||
print("this should not be in the output file");
|
||||
redirect_output("example.out");
|
||||
|
||||
auto [i, j] = read<int, int>();
|
||||
print(i, j);
|
||||
|
||||
|
@ -68,4 +71,12 @@ signed main() {
|
|||
print(map<int, string>{{3,"three"},{1,"one"}});
|
||||
print(tuple{unordered_map<int, string>{{3,"three"},{1,"one"}}});
|
||||
print(unordered_set<int>{3,1,4});
|
||||
|
||||
redirect_input("example.in");
|
||||
print("reading from example.in:", read_string());
|
||||
redirect_input("example.in");
|
||||
print("reading from example.in:", read_string());
|
||||
print("this is the last line on example.out");
|
||||
reset_output();
|
||||
print("this is stdout only");
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ snprintf(char *buffer, std::size_t buf_size, const char *format, ...);
|
|||
#define puts puts_is_evil
|
||||
#define fputs fputs_is_evil
|
||||
#define fgets fgets_is_evil
|
||||
#define freopen freopen_is_evil
|
||||
#define fopen fopen_is_evil
|
||||
#define fclose fclose_is_evil
|
||||
#define fflush fflush_is_evil
|
||||
|
@ -48,8 +47,6 @@ snprintf(char *buffer, std::size_t buf_size, const char *format, ...);
|
|||
[[deprecated("<cstdio> is evil. Use cin/cout.")]] char *
|
||||
fgets(char *str, int count, FILE *stream);
|
||||
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::FILE *
|
||||
freopen(const char *filename, const char *mode, std::FILE *stream);
|
||||
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::FILE *
|
||||
fopen(const char *filename, const char *mode);
|
||||
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int
|
||||
fclose(std::FILE *stream);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
#include <ostream>
|
||||
#include <streambuf>
|
||||
|
||||
namespace soi {
|
||||
|
||||
namespace redirect {
|
||||
|
||||
class teebuf : public std::streambuf {
|
||||
std::streambuf *sb1_;
|
||||
std::streambuf *sb2_;
|
||||
|
||||
int overflow(int c) {
|
||||
using traits = std::streambuf::traits_type;
|
||||
bool rc = true;
|
||||
if (!traits::eq_int_type(traits::eof(), c)) {
|
||||
traits::eq_int_type(this->sb1_->sputc(c), traits::eof()) && (rc = false);
|
||||
traits::eq_int_type(this->sb2_->sputc(c), traits::eof()) && (rc = false);
|
||||
}
|
||||
return rc ? traits::not_eof(c) : traits::eof();
|
||||
}
|
||||
int sync() {
|
||||
bool rc = false;
|
||||
this->sb1_->pubsync() != -1 || (rc = false);
|
||||
this->sb2_->pubsync() != -1 || (rc = false);
|
||||
return rc ? -1 : 0;
|
||||
}
|
||||
|
||||
public:
|
||||
teebuf(std::streambuf *sb1, std::streambuf *sb2) : sb1_(sb1), sb2_(sb2) {}
|
||||
};
|
||||
|
||||
static std::streambuf *checked_rdbuf(std::ios &stream, const char *filename,
|
||||
const char *action) {
|
||||
if (!stream) {
|
||||
std::cerr << "ERROR: can't open to file " << filename << " for " << action
|
||||
<< '\n';
|
||||
std::exit(-1);
|
||||
}
|
||||
return stream.rdbuf();
|
||||
}
|
||||
|
||||
struct output_redirector {
|
||||
std::ofstream fout;
|
||||
teebuf tee;
|
||||
std::streambuf *old_cout;
|
||||
|
||||
output_redirector(const char *filename)
|
||||
: fout(filename),
|
||||
tee(checked_rdbuf(fout, filename, "writing"), std::cout.rdbuf()),
|
||||
old_cout(std::cout.rdbuf(&tee)) {}
|
||||
|
||||
~output_redirector() { std::cout.rdbuf(old_cout); }
|
||||
};
|
||||
|
||||
struct input_redirector {
|
||||
std::ifstream fin;
|
||||
std::streambuf *old_cin;
|
||||
|
||||
input_redirector(const char *filename)
|
||||
: fin(filename),
|
||||
old_cin(std::cin.rdbuf(checked_rdbuf(fin, filename, "reading"))) {}
|
||||
|
||||
~input_redirector() { std::cin.rdbuf(old_cin); }
|
||||
};
|
||||
|
||||
std::forward_list<output_redirector> output_redirectors;
|
||||
std::unique_ptr<input_redirector> the_input_redirector;
|
||||
|
||||
} // namespace redirect
|
||||
|
||||
} // namespace soi
|
||||
|
||||
void redirect_output(const char *filename) {
|
||||
soi::redirect::output_redirectors.emplace_front(filename);
|
||||
}
|
||||
void redirect_output(std::string const &filename) {
|
||||
redirect_output(filename.c_str());
|
||||
}
|
||||
void reset_output() {
|
||||
soi::redirect::output_redirectors.clear();
|
||||
}
|
||||
|
||||
void reset_input() {
|
||||
soi::redirect::the_input_redirector.reset();
|
||||
}
|
||||
void redirect_input(const char *filename) {
|
||||
reset_input();
|
||||
auto next = new soi::redirect::input_redirector(filename);
|
||||
soi::redirect::the_input_redirector.reset(next);
|
||||
}
|
||||
void redirect_input(std::string const &filename) {
|
||||
redirect_input(filename.c_str());
|
||||
}
|
|
@ -77,7 +77,7 @@ soi_initializer soi_initializer_{false};
|
|||
} // end namespace soi
|
||||
|
||||
#include "bits/soi-io.hpp"
|
||||
|
||||
#include "bits/soi-redirect.hpp"
|
||||
#include "bits/soi-deprecate.hpp"
|
||||
|
||||
#define int int64_t
|
||||
|
|
Loading…
Reference in New Issue