1

我正在尝试创建一个自定义std::streambuf,它充当父流的子流。这是对此 SO 线程答案中概述的实现的改编。

在下面的这个例子中,我试图简单地读取"Hello,"流的前 5 个字符。但是,当我调用 时ifstream.read()buffer缓冲区充满了"ello, ",就好像它被关闭了一样。

#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, "
}

我是streambufs 的新手,我觉得我在这里遗漏了一些明显的东西。任何帮助,将不胜感激。

这是 的定义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;
    };
};
4

1 回答 1

1

当我第一次看到代码时,我觉得这很奇怪。

int uflow()
{
    // ...
    return m_sbuf->snextc();
}

他为什么要返回结果snextc()?定义的策略uflow()是“返回下一个可用字符并将输入流推进一个字符”。如果snextc()被调用,输入序列将被推进,然后它会返回下一个字符。结果是至少跳过了 1 个字符。

正确的调用方法是sbumpc()因为它会先缓存下一个字符推进输入流,然后返回它。

return m_sbuf->sbumpc();

这是一个演示。

于 2014-03-06T12:23:58.280 回答