Skip to content

Instantly share code, notes, and snippets.

@yohhoy
Created August 16, 2012 13:31
Show Gist options
  • Save yohhoy/3370099 to your computer and use it in GitHub Desktop.
Save yohhoy/3370099 to your computer and use it in GitHub Desktop.
FizzBuzz stream
#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
}
@yohhoy
Copy link
Author

yohhoy commented Apr 13, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment