#include <iostream>
#include <array>
#include <functional>
#include <algorithm>
class formatting_streambuf: public std::streambuf
{
typedef std::function<std::string(const std::string&)> formatter_t;
public:
formatting_streambuf(std::streambuf* buf, const formatter_t& formatter) : buffer_{}, buf_(buf), formatter_(formatter)
{
setp(buffer_.begin(), buffer_.end() - 1);
}
protected:
virtual int overflow(int_type c = traits_type::eof()) override
{
*pptr() = traits_type::to_char_type(c);
format();
return traits_type::not_eof(c);
}
virtual int sync() override
{
format();
return 0;
}
private:
void format()
{
const std::string value(buffer_.begin(), pptr() - buffer_.begin());
const std::string formatted = formatter_(value);
buf_->sputn(formatted.c_str(), formatted.size());
setp(buffer_.begin(), buffer_.end());
}
std::array<char, 1024> buffer_;
std::streambuf* buf_;
formatter_t formatter_;
};
class formatting_ostream : public std::ostream
{
typedef std::function<std::string(const std::string&)> formatter_t;
public:
formatting_ostream(std::ostream& stream, const formatter_t& formatter) :
stream_(stream), old_buf_(stream_.rdbuf()), streambuf_(old_buf_, formatter)
{
init(&streambuf_);
}
private:
std::ostream& stream_;
std::streambuf* old_buf_;
formatting_streambuf streambuf_;
};
class source
{
public:
source(std::ostream& stream) : stream_(stream)
{
}
void print()
{
stream_ << "HeLlO" << std::endl;
}
private:
std::ostream& stream_;
};
int main()
{
auto to_lower = [](const std::string& v) -> std::string
{
std::string result;
std::transform(v.begin(), v.end(), std::back_inserter(result), tolower);
return result;
};
formatting_ostream stream(std::cout, to_lower);
source s(stream);
s.print();
s.print();
source ss(std::cout);
ss.print();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YXJyYXk+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8YWxnb3JpdGhtPgogCmNsYXNzIGZvcm1hdHRpbmdfc3RyZWFtYnVmOiBwdWJsaWMgc3RkOjpzdHJlYW1idWYKewogICB0eXBlZGVmIHN0ZDo6ZnVuY3Rpb248c3RkOjpzdHJpbmcoY29uc3Qgc3RkOjpzdHJpbmcmKT4gZm9ybWF0dGVyX3Q7CnB1YmxpYzoKICAgZm9ybWF0dGluZ19zdHJlYW1idWYoc3RkOjpzdHJlYW1idWYqIGJ1ZiwgY29uc3QgZm9ybWF0dGVyX3QmIGZvcm1hdHRlcikgOiBidWZmZXJfe30sIGJ1Zl8oYnVmKSwgZm9ybWF0dGVyXyhmb3JtYXR0ZXIpCiAgIHsKICAgICAgc2V0cChidWZmZXJfLmJlZ2luKCksIGJ1ZmZlcl8uZW5kKCkgLSAxKTsKICAgfQpwcm90ZWN0ZWQ6CiAgIHZpcnR1YWwgaW50IG92ZXJmbG93KGludF90eXBlIGMgPSB0cmFpdHNfdHlwZTo6ZW9mKCkpIG92ZXJyaWRlCiAgIHsKICAgICAgKnBwdHIoKSA9IHRyYWl0c190eXBlOjp0b19jaGFyX3R5cGUoYyk7CiAgICAgIGZvcm1hdCgpOwogICAgICByZXR1cm4gdHJhaXRzX3R5cGU6Om5vdF9lb2YoYyk7CiAgIH0KIAogICB2aXJ0dWFsIGludCBzeW5jKCkgb3ZlcnJpZGUKICAgewogICAgICBmb3JtYXQoKTsKICAgICAgcmV0dXJuIDA7CiAgIH0KcHJpdmF0ZToKICAgdm9pZCBmb3JtYXQoKQogICB7CiAgICAgIGNvbnN0IHN0ZDo6c3RyaW5nIHZhbHVlKGJ1ZmZlcl8uYmVnaW4oKSwgcHB0cigpIC0gYnVmZmVyXy5iZWdpbigpKTsKICAgICAgY29uc3Qgc3RkOjpzdHJpbmcgZm9ybWF0dGVkID0gZm9ybWF0dGVyXyh2YWx1ZSk7CiAgICAgIGJ1Zl8tPnNwdXRuKGZvcm1hdHRlZC5jX3N0cigpLCBmb3JtYXR0ZWQuc2l6ZSgpKTsKICAgICAgc2V0cChidWZmZXJfLmJlZ2luKCksIGJ1ZmZlcl8uZW5kKCkpOwogICB9CiAKICAgc3RkOjphcnJheTxjaGFyLCAxMDI0PiBidWZmZXJfOwogICBzdGQ6OnN0cmVhbWJ1ZiogYnVmXzsKICAgZm9ybWF0dGVyX3QgZm9ybWF0dGVyXzsKfTsKIApjbGFzcyBmb3JtYXR0aW5nX29zdHJlYW0gOiBwdWJsaWMgc3RkOjpvc3RyZWFtCnsKICAgdHlwZWRlZiBzdGQ6OmZ1bmN0aW9uPHN0ZDo6c3RyaW5nKGNvbnN0IHN0ZDo6c3RyaW5nJik+IGZvcm1hdHRlcl90OwpwdWJsaWM6CiAgIGZvcm1hdHRpbmdfb3N0cmVhbShzdGQ6Om9zdHJlYW0mIHN0cmVhbSwgY29uc3QgZm9ybWF0dGVyX3QmIGZvcm1hdHRlcikgOiAKICAgICAgc3RyZWFtXyhzdHJlYW0pLCBvbGRfYnVmXyhzdHJlYW1fLnJkYnVmKCkpLCBzdHJlYW1idWZfKG9sZF9idWZfLCBmb3JtYXR0ZXIpCiAgIHsKICAgICAgaW5pdCgmc3RyZWFtYnVmXyk7CiAgIH0KcHJpdmF0ZToKICAgc3RkOjpvc3RyZWFtJiBzdHJlYW1fOwogICBzdGQ6OnN0cmVhbWJ1Ziogb2xkX2J1Zl87CiAgIGZvcm1hdHRpbmdfc3RyZWFtYnVmIHN0cmVhbWJ1Zl87Cn07CiAKY2xhc3Mgc291cmNlCnsKcHVibGljOgogICBzb3VyY2Uoc3RkOjpvc3RyZWFtJiBzdHJlYW0pIDogc3RyZWFtXyhzdHJlYW0pCiAgIHsKICAgfQogCiAgIHZvaWQgcHJpbnQoKQogICB7CiAgICAgIHN0cmVhbV8gPDwgIkhlTGxPIiA8PCBzdGQ6OmVuZGw7CiAgIH0KcHJpdmF0ZToKICAgc3RkOjpvc3RyZWFtJiBzdHJlYW1fOwp9OwogCmludCBtYWluKCkKewogICBhdXRvIHRvX2xvd2VyID0gW10oY29uc3Qgc3RkOjpzdHJpbmcmIHYpIC0+IHN0ZDo6c3RyaW5nCiAgIHsKICAgICAgc3RkOjpzdHJpbmcgcmVzdWx0OwogICAgICBzdGQ6OnRyYW5zZm9ybSh2LmJlZ2luKCksIHYuZW5kKCksIHN0ZDo6YmFja19pbnNlcnRlcihyZXN1bHQpLCB0b2xvd2VyKTsKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgfTsKICAgZm9ybWF0dGluZ19vc3RyZWFtIHN0cmVhbShzdGQ6OmNvdXQsIHRvX2xvd2VyKTsKICAgc291cmNlIHMoc3RyZWFtKTsKICAgcy5wcmludCgpOwogICBzLnByaW50KCk7CiAKICAgc291cmNlIHNzKHN0ZDo6Y291dCk7CiAgIHNzLnByaW50KCk7Cn0=