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 streambufs , 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(); 

here demo.


Comments

Popular posts from this blog

c# - How to get the current UAC mode -

postgresql - Lazarus + Postgres: incomplete startup packet -

javascript - Ajax jqXHR.status==0 fix error -