-
Sam Yates authored5a10461f
ioutil.hpp 2.49 KiB
#pragma once
#include <iostream>
namespace nest {
namespace mc {
namespace util {
class iosfmt_guard {
public:
explicit iosfmt_guard(std::ios& stream) :
save_(nullptr), stream_(stream)
{
save_.copyfmt(stream_);
}
~iosfmt_guard() {
stream_.copyfmt(save_);
}
private:
std::ios save_;
std::ios& stream_;
};
template <typename charT, typename traitsT = std::char_traits<charT> >
class basic_null_streambuf: public std::basic_streambuf<charT, traitsT> {
private:
typedef typename std::basic_streambuf<charT, traitsT> streambuf_type;
public:
typedef typename streambuf_type::char_type char_type;
typedef typename streambuf_type::int_type int_type;
typedef typename streambuf_type::pos_type pos_type;
typedef typename streambuf_type::off_type off_type;
typedef typename streambuf_type::traits_type traits_type;
virtual ~basic_null_streambuf() {}
protected:
std::streamsize xsputn(const char_type* s, std::streamsize count) override {
return count;
}
int_type overflow(int_type c) override {
return traits_type::not_eof(c);
}
};
class mask_stream {
public:
explicit mask_stream(bool mask): mask_(mask) {}
operator bool() const { return mask_; }
template <typename charT, typename traitsT>
friend std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& O, const mask_stream& F) {
int xindex = get_xindex();
std::basic_streambuf<charT, traitsT>* saved_streambuf =
static_cast<std::basic_streambuf<charT, traitsT>*>(O.pword(xindex));
if (F.mask_ && saved_streambuf) {
// re-enable by restoring saved streambuf
O.pword(xindex) = 0;
O.rdbuf(saved_streambuf);
}
else if (!F.mask_ && !saved_streambuf) {
// disable stream but save old streambuf
O.pword(xindex) = O.rdbuf();
O.rdbuf(get_null_streambuf<charT, traitsT>());
}
return O;
}
private:
// our key for retrieve saved streambufs.
static int get_xindex() {
static int xindex = std::ios_base::xalloc();
return xindex;
}
template <typename charT, typename traitsT>
static std::basic_streambuf<charT, traitsT>* get_null_streambuf() {
static basic_null_streambuf<charT, traitsT> the_null_streambuf;
return &the_null_streambuf;
}
// true => do not filter
bool mask_;
};
} // namespace util
} // namespace mc
} // namespace nest