Reputation: 3665
Combining this answer on in-memory streams with this answer on seekoff
, I implemented an in-memory buffer as follows:
struct membuf : std::streambuf {
membuf(char const* base, size_t size) {
char* p(const_cast<char*>(base));
this->setg(p, p, p + size);
}
};
struct imemstream : virtual membuf, std::istream {
imemstream(char const* base, size_t size) :
membuf(base, size),
std::istream(static_cast<std::streambuf*>(this)) {
}
std::iostream::pos_type seekoff(std::iostream::off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which = std::ios_base::in) {
if (dir == std::ios_base::cur) gbump(off);
return gptr() - eback();
}
};
However, as explained in the comments of the first aswer, we still need to get seekg
/seekpos
working. So how to correctly implement seekpos
here?
PS This question goes in the same direction, but gives a more specific answer.
Upvotes: 2
Views: 1778
Reputation: 731
Since this hasn't been answered, I'm posting the implementation proposed here.
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
}
Also, the implementation of seekoff
did not work for me in the case of other directions. Consider amending it by the following:
pos_type seekoff(off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which = std::ios_base::in) override {
if (dir == std::ios_base::cur)
gbump(off);
else if (dir == std::ios_base::end)
setg(eback(), egptr() + off, egptr());
else if (dir == std::ios_base::beg)
setg(eback(), eback() + off, egptr());
return gptr() - eback();
}
Upvotes: 12