You can definitely do this by implementing a filtering stream buffer: you should get from std::streambuf and take the range that you want to set, and the base stream buffer (well, a pointer to it) as arguments. Then you will look for a place to start. The underflow() function will read from the base stream buffer into its buffer until it underflow() as many characters as desired. Here is a somewhat crude and completely untested version:
#include <streambuf> struct rangebuf: std::streambuf { rangebuf(std::streampos start, size_t size, std::streambuf* sbuf): size_(size), sbuf_(sbuf) { sbuf->seekpos(start, std::ios_base::in); } int underflow() { size_t r(this->sbuf_->sgetn(this->buf_, std::min<size_t>(sizeof(this->buf_), this->size_)); this->size -= r; this->setg(this->buf_, this->buf_, this->buf_ + r); return this->gptr() == this->egptr() ? traits_type::eof() : traits_type::to_int_type(*this->gptr()); } size_t size_; std::streambuf* sbuf_; };
You can use a pointer to an instance of this stream buffer to initialize std::istream . If this is a recurring need, you might want to create a class derived from std::istream , instead creating a stream buffer.
source share