c++ - Creating a substreambuf to read from an existing istream -
i'm attempting create custom std::streambuf
acts sub-stream parent stream. adaptation of implementation outlined in this thread answer.
in example below attempting read first 5 characters "hello,"
of stream. however, when call ifstream.read()
buffer
, buffer filled "ello, "
, though off one.
#include <iostream> #include <sstream> using namespace std; int main() { stringstream ss; ss << "hello, world!"; substreambuf asd(ss.rdbuf(), 0, 5); istream istream(&asd); char buffer[6] = { '\0' }; istream.read(buffer, sizeof(buffer)); cout << buffer << endl; //prints "ello, " }
i new streambuf
s , feel i'm missing obvious here. appreciated.
here definition substreambuf
:
#include <iostream> #include <sstream> namespace std { struct substreambuf : public streambuf { explicit substreambuf(streambuf* sbuf, streampos pos, streampos len) : m_sbuf(sbuf), m_pos(pos), m_len(len), m_read(0) { m_sbuf->pubseekpos(pos); setbuf(nullptr, 0); } protected: int underflow() { if (m_read >= m_len) { return traits_type::eof(); } return m_sbuf->sgetc(); } int uflow() { if (m_read >= m_len) { return traits_type::eof(); } m_read += 1; return m_sbuf->snextc(); } streampos seekoff(streamoff off, ios_base::seekdir seekdir, ios_base::openmode openmode = ios_base::in | ios_base::out) { if (seekdir == ios_base::beg) { off += m_pos; } else if (seekdir == ios_base::cur) { off += m_pos + m_read; } else if (seekdir == ios_base::end) { off += m_pos + m_len; } return m_sbuf->pubseekpos(off, openmode) - m_pos; } streampos seekpos(streampos streampos, ios_base::openmode openmode = ios_base::in | ios_base::out) { streampos += m_pos; if (streampos > m_pos + m_len) { return -1; } return m_sbuf->pubseekpos(streampos, openmode) - m_pos; } private: streambuf* m_sbuf; streampos m_pos; streamsize m_len; streampos m_read; }; };
i thought strange when first saw code.
int uflow() { // ... return m_sbuf->snextc(); }
why returning result of snextc()
? policy defined uflow()
"return next available character , advance input stream 1 character". if snextc()
called, input sequence advanced, and then return next character. result @ least 1 character skipped.
the correct method call sbumpc()
because cache next character first, advance input stream, , return it.
return m_sbuf->sbumpc();
Comments
Post a Comment