streambuf::xsgetn和状态标志

streambuf::xsgetn and state flags

本文关键字:标志 状态 xsgetn streambuf      更新时间:2023-10-16

受保护的虚拟成员函数streambuf::xsgetn使I/O流实现者能够定义一个从输入流中提取n字符并将其存储在缓冲区中的函数。

通常,对于大多数标准流(如fstream),此函数只需在循环中调用sbumpc,直到返回eof。但是,自定义流类可以覆盖此函数以执行更高效的操作,例如将数据批量复制到输出缓冲区中。

但我不明白的是,xsgetn是如何指示已经达到EOF条件的。假设用户请求读取100个字节,但流中只剩下50个字节。假定xsgetn应该读取50个字节,返回50,然后将内部流状态设置为eof

除了xsgetstreambuf的成员函数,它没有办法设置流状态。与可以返回EOFsbumpc不同,xsgetn无法指示EOF条件发生。那么xsgetn应该如何处理EOF条件呢?

这是我在libstdc++上发现的:

template<typename _CharT, typename _Traits>
streamsize basic_streambuf<_CharT, _Traits>::xsgetn(char_type* __s, streamsize __n) {
    streamsize __ret = 0;
    while (__ret < __n) {
        const streamsize __buf_len = this->egptr() - this->gptr();
        if (__buf_len) {
            const streamsize __remaining = __n - __ret;
            const streamsize __len = std::min(__buf_len, __remaining);
            traits_type::copy(__s, this->gptr(), __len);
            __ret += __len;
            __s += __len;
            this->__safe_gbump(__len);
        }
        if (__ret < __n) {
            const int_type __c = this->uflow();
            if (!traits_type::eq_int_type(__c, traits_type::eof())) {
                traits_type::assign(*__s++, traits_type::to_char_type(__c));
                ++__ret;
            } else
                break;
        }
    }
    return __ret;
}

当提取的字符少于请求的字符数时,此函数调用uflow()以获取更多字符。如果该函数返回Traits::eof(),那么它将简单地返回是否提取了0个字符。函数调用的结果由访问流状态的高级流操作获取,并将相应地进行设置。