Created
August 16, 2012 13:31
-
-
Save yohhoy/3370099 to your computer and use it in GitHub Desktop.
FizzBuzz stream
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ostream> | |
#include <string> | |
#include <locale> | |
// FizzBuzz streambuf | |
template <class CharT, class Traits = std::char_traits<CharT> > | |
class basic_fizzbuzz_streambuf : public std::basic_streambuf<CharT, Traits> { | |
typedef std::basic_streambuf<CharT, Traits> sbuf_type; | |
typedef typename sbuf_type::traits_type traits_type; | |
typedef typename sbuf_type::char_type char_type; | |
typedef typename sbuf_type::int_type int_type; | |
sbuf_type& sb_; | |
bool mul5_; | |
int acc3_; | |
std::basic_string<char_type, traits_type> tb_; | |
char_type widen(char c) const | |
{ | |
return std::use_facet<std::ctype<char_type> >(sb_.getloc()).widen(c); | |
} | |
void putn(const char* s) const | |
{ | |
while (*s) | |
sb_.sputc(widen(*s++)); | |
} | |
virtual int sync() | |
{ | |
if (!tb_.empty()) { | |
bool mul3 = (acc3_ % 3 == 0); | |
if (mul3 && mul5_) | |
putn("FizzBuzz"); | |
else if (mul5_) | |
putn("Buzz"); | |
else if (mul3) | |
putn("Fizz"); | |
else | |
sb_.sputn(tb_.data(), tb_.size()); | |
tb_.clear(); | |
acc3_ = 0; | |
} | |
return 0; | |
} | |
virtual int_type overflow(int_type ch) | |
{ | |
if (ch == traits_type::eof()) | |
return ch; | |
char_type c = traits_type::to_char_type(ch); | |
if (std::isdigit(c, sb_.getloc())) { | |
tb_.push_back(c); | |
acc3_ += (c - widen('0')); | |
mul5_ = (c == widen('0') || c == widen('5')); | |
} else { | |
sync(); | |
sb_.sputc(c); | |
} | |
return ch; | |
} | |
public: | |
basic_fizzbuzz_streambuf(sbuf_type& sb) | |
: sb_(sb), mul5_(false), acc3_(0) | |
{ | |
this->setp(0, 0); | |
} | |
}; | |
typedef basic_fizzbuzz_streambuf<char> fizzbuzz_streambuf; | |
typedef basic_fizzbuzz_streambuf<wchar_t> fizzbuzz_wstreambuf; | |
// helper class | |
template <class CharT, class Traits = std::char_traits<CharT> > | |
class basic_fizzbuzznizer { | |
std::basic_ostream<CharT, Traits>& target_; | |
std::basic_streambuf<CharT, Traits>* oldbuf_; | |
public: | |
basic_fizzbuzznizer(std::basic_ostream<CharT, Traits>& os) | |
: target_(os), oldbuf_(os.rdbuf()) | |
{ | |
target_.rdbuf(new basic_fizzbuzz_streambuf<CharT, Traits>(*oldbuf_)); | |
} | |
~basic_fizzbuzznizer() | |
{ | |
delete target_.rdbuf(oldbuf_); | |
} | |
}; | |
typedef basic_fizzbuzznizer<char> fizzbuzznizer; | |
typedef basic_fizzbuzznizer<wchar_t> wfizzbuzznizer; | |
//--------------------------------------------------------------------------- | |
#include <iostream> | |
const int N = 100; | |
template <class OutputStream> | |
void countup(OutputStream& os) | |
{ | |
for (int i = 1; i <= N; ++i) | |
os << i << os.widen(' '); | |
os << std::endl; | |
} | |
int main() | |
{ | |
#if 1 | |
countup(std::wcout); | |
wfizzbuzznizer fb(std::wcout); | |
countup(std::wcout); | |
#else | |
countup(std::cout); | |
fizzbuzznizer fb(std::cout); | |
countup(std::cout); | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://yohhoy.hatenablog.jp/entries/2013/04/14