streambuf::xsgetn 和州旗

streambuf::xsgetn and state flags

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

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

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

除了xsgetstreambuf的成员函数,它没有办法设置流状态。与 sbumpc 不同的是,它可以 return EOF,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()获取更多的字符。如果该函数 returns Traits::eof() 那么它只会 return 无论是否提取了 0 个字符。函数调用的结果由有权访问流状态的更高级别的流操作获取,并将相应地设置它。