我有以下基于例如的实现: 这个问题和答案
struct membuf : std::streambuf
{
membuf(char* begin, char* end)
{
this->setg(begin, begin, end);
}
protected:
virtual pos_type seekoff(off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which = std::ios_base::in)
{
std::istream::pos_type ret;
if(dir == std::ios_base::cur)
{
this->gbump(off);
}
// something is missing here...
}
};
我想按以下方式在我的方法中使用它:
char buffer[] = { 0x01, 0x0a };
membuf sbuf(buffer, buffer + sizeof(buffer));
std::istream in(&sbuf);
然后致电,例如
tellg()
上 in
并得到正确的结果。
到目前为止,它几乎是完美的 - 它不会在流结束时停止。
我应该如何升级它才能正常工作?
我的主要动机是模仿
std::ifstream
行为,但在测试中将二进制 char[]
输入到它们中(而不是依赖于二进制文件)。
接受的答案不适用于搜索方向设置为
std::ios_base::beg
或 std::ios_base::end
的情况。为了支持这些案例,请通过以下方式扩展实施:
pos_type seekoff(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);
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();
}
看来我错过了当前位置的回报。所以
seekoff
的最终实现如下:
pos_type seekoff(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();
}
至少对于 GCC 来说,如果
seekg
超过结束指针,你会遇到严重崩溃,例如:
file.seekg(10, std::ios::end);
为了防止崩溃,您需要信号超出绑定错误:
virtual std::streambuf::pos_type seekoff(
std::streambuf::off_type off, std::ios_base::seekdir dir,
std::ios_base::openmode) override
{
auto pos = gptr();
if (dir == std::ios_base::cur)
pos += off;
else if (dir == std::ios_base::end)
pos = egptr() + off;
else if (dir == std::ios_base::beg)
pos = eback() + off;
//check bunds
if (pos < eback())
return std::streambuf::pos_type(-1);
else if (pos > egptr())
return std::streambuf::pos_type(-1);
setg(eback(), pos, egptr());
return gptr() - eback();
}