Nov 29, 2014 at 10:37pm UTC
Hello, I'm try to extend a std::streambuf, to forward the data over a socket.
The issue I am facing is that it does not reset the sync() state, once reached...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
class tcp_stream: public std::streambuf {
char * buffer;
const static std::size_t buffer_sz; //=4
...
/**
* Contract with streambuf
* @Override
*/
int overflow (int c);
/**
* Contract with streambuf
* @Override
*/
std::streamsize xsputn (const char * s, std::streamsize n);
/**
* Contract with streambuf
* @Override
*/
int sync();
...
}
And this is my implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
void tcp_stream::resetp(){ // invoked in the ctor
setp(buffer, buffer + buffer_sz -1);
}
int tcp_stream::overflow(int ch){
cout << "[overflow] " << ch << "; base pointer: " << uint64_t(pbase()) << " put pointer: " << uint64_t(pptr()) << endl;
// edge case
if ( ch == traits_type::eof() || pptr() >= epptr() ) return traits_type::eof();
cout << "added!" << endl;
*pptr() = ch;
pbump(1);
return traits_type::to_int_type(ch);
}
int tcp_stream::sync(){
cout << "[sync]" << endl;
resetp();
cout << "[sync end] base pointer: " << uint64_t(pbase()) << " put pointer: " << uint64_t(pptr()) << endl;
return 0;
}
std::streamsize tcp_stream::xsputn (const char * s, std::streamsize n){
cout << "[xsputn] (" << s << ", " << n << ")" << endl;
ptrdiff_t diff = epptr() - pptr();
memcpy(buffer, s, diff);
pbump(diff);
return diff;
}
When it reaches the EOF, all the subsequent writings always invoke sync(). For instance:
1 2 3 4 5 6 7 8
craic::tcp_stream tcps;
clog.rdbuf(&tcps);
std::string str;
while ( cin >> skipws >> str ){
cout << "Input string: " << str << endl;
clog << str.c_str() << endl;
}
Assuming an internal buffer of 4 for my custom stringbuf, it produces:
1 2 3 4 5 6 7 8 9 10 11 12
alpha
Input string: alpha
[xsputn] (alpha, 5) // OK
[sync]
[sync end] base pointer: 8007936 put pointer: 8007936
beta
Input string: beta
[sync] // It misses the write
[sync end] base pointer: 8007936 put pointer: 8007936
Input string: gamma
[sync] // And again...
[sync end] base pointer: 8007936 put pointer: 8007936
So.. how do I properly reset the buffer to the correct state?
Thanks,
Dean
Last edited on Nov 29, 2014 at 10:38pm UTC
Nov 30, 2014 at 1:09am UTC
Looks like for your buffer of 4, xsputn("alpha",5) returns 3, indicating that the output didn't complete. The stream gets its badbit set and doesn't do anything else (well, clang doesn't, gcc is calling sync)
xsputn is supposed to write everything, calling overflow as needed.
There's already a tcpstream in boost.asio, by the way.