Reputation: 10490
What's wrong with my overflow()
here. When I print oss.str()
it prints "Hello, Wor"
instead of "Hello, World"
. What did I do wrong?
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
class io_buffer : public std::streambuf
{
public:
io_buffer(std::ostream& os, int buf_size = 4)
: os_(os), buffer(buf_size)
{
os_.clear();
char* beg = buffer.data();
setp(beg, beg + buffer.size());
}
int_type overflow(int_type c)
{
if (os_ && !traits_type::eq_int_type(c, traits_type::eof()))
{
*pptr() = traits_type::to_char_type(c);
pbump(1);
if (flush())
{
setp(buffer.data(), buffer.data() + buffer.size());
return c;
} else
return traits_type::eof();
}
return traits_type::not_eof(c);
}
bool flush()
{
return os_.write(pbase(), pptr() - pbase());
}
int sync()
{
return flush() ? 0 : -1;
}
private:
std::ostream& os_;
std::vector<char> buffer;
};
int main()
{
std::ostringstream oss;
io_buffer buf(oss);
std::ostream os(&buf);
std::string str("Hello, World");
os << str;
std::cout << oss.str() << std::endl;
}
Upvotes: 1
Views: 250
Reputation: 29754
You need to flush also a std::vector
(buffer), i.e:
int_type overflow(int_type c)
{
if (os_ && !traits_type::eq_int_type(c, traits_type::eof()))
{
*pptr() = traits_type::to_char_type(c);
pbump(1);
if (flush())
{
buffer.clear(); // <-
setp(buffer.data(), buffer.data() + buffer.size());
return c;
} else
return traits_type::eof();
}
return traits_type::not_eof(c);
}
Even better, as 0x499602D2 address suggested use pbump(-buffer.size())
to avoid multiple calls to overflow()
.
Watch out for your destructor as it is required to do a flush:
Upvotes: 1
Reputation: 50046
The problem is that you use:
setp(beg, beg + buffer.size());
and in overflow() you add new element with no reallocation, the end pointer should be accessible (if you dont want to reallocate), otherwise you need to reallocate your buffer in overflow(). So change it to:
setp(beg, beg + buffer.size() - 1);
in io_buffer constructor
and later in overflow change setp to:
pbump(-(pptr() - pbase()));
also to flush your buffer add endl:
os << str << endl;
working example: http://coliru.stacked-crooked.com/a/7c72ecfe78bb2aee
Upvotes: 1