如何实现自定义std::streambuf的seekoff()函数?

7

我基于如此问题和答案所述的方法实现了以下内容:

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);

然后在in上调用tellg(),就可以得到正确的结果。

到目前为止,这几乎是完美的 - 它不会在流的末尾停止。

我该如何更新它,使其正常工作呢?

我的主要动机是模仿std::ifstream的行为,但在测试中使用二进制char[](而不是依赖于二进制文件)。


你是什么意思说“它不停止”? - SergeyA
@SergeyA 在我的客户端代码中,我调用了in.tellg()并检查它是否小于我期望的“目标”位置。这会失败并在循环中读取比我想要的多一个元素。 - Patryk
仍然不清楚您所指的“失败”是什么意思。tellg 应该会告诉您缓冲区的当前位置,没有多余或者减少。如果您已经超过了缓冲区限制,tellg 将会告诉您这一点。 - SergeyA
@SergeyA 我想我搞定了。我在注释部分添加了 return gptr() - eback();,现在它可以工作了 :) - Patryk
2个回答

9
接受的答案对于将搜索方向设置为 std::ios_base::begstd::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();
}

5

看起来我漏掉了当前位置的返回。 因此,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();
  }

给那位点了-1的人:您有什么评论吗? - Patryk
如果 off 将获取指针推到缓冲区的开头或结尾之外怎么办?如果有人试图寻找开头或结尾会怎样? - rdb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接