继承 ostream 和 xsputn 和 Overflow 的 Streambuf 问题

inheriting ostream and streambuf problem with xsputn and overflow

本文关键字:Streambuf 问题 xsputn ostream 继承 Overflow      更新时间:2023-10-16

我一直在研究创建自己的ostream,以及一个streambuf来处理我的ostream的缓冲区。 我实际上大部分工作,我可以将 (<<( 插入到我的流中并毫无问题地获取字符串。 我通过暗示虚拟函数xsputn来做到这一点。 但是,如果我在流中输入 (<<( 浮点数或整数而不是字符串 xsputn 永远不会被调用。

我已经浏览了代码,我看到流正在调用do_put,然后f_put最终尝试将浮点数 1 个字符一次放入缓冲区。 如果我离开没有空间的缓冲区,我可以让它调用我的虚拟函数溢出(int c(的实现,从而获取浮点数和整数的数据。

现在问题来了,我需要知道浮点何时完成放入缓冲区。 或者换句话说,我需要知道这是最后一次为正在流式传输的特定值调用溢出的时间。 xsputn 对我有用的原因是因为我预先获得了整个值及其长度。 所以我可以将其复制到缓冲区中,然后调用等待缓冲区已满的函数。

我承认滥用了 ostream 设计,因为我需要缓存输出,然后为每个输入值 (<<( 一次发送所有输出。

无论如何,为了清楚起见,我将以另一种方式重申我正在拍摄的内容。 很有可能我只是以错误的方式去做。

我想使用继承的 ostream 和 streambuf,以便我可以在其中输入值并允许它为我处理我的类型转换,然后我想将这些信息转移到另一个对象,我将句柄传递给 streambuf 到(for?(。 该对象具有昂贵的 I/O,所以我不想一次发送 1 个字符的数据。

如果不清楚,提前抱歉。 谢谢你的时间。

不太

清楚你在做什么,尽管听起来很粗略右。 可以肯定的是:您的ostream所做的只是提供方便构造函数创建和安装您的streambuf,析构函数,可能还有 rdbuf 的实现处理正确类型的缓冲区。 假设这是真的:在streambuf中定义xsputn纯粹是一种优化。您必须定义的关键功能是 overflow . 最简单的overflow的实现只需要一个字符,并且将其输出到接收器。 除此之外的一切都是优化:例如,您可以使用setp设置缓冲区;如果你这样做this,则overflow只有当缓冲区已满,或请求刷新。 在这种情况下,您必须输出缓冲区(使用 pbasepptr 来获取地址(。 (streambuf基类初始化用于创建 0 长度缓冲区的指针,因此overflow将是要求每个字符。 您可能使用的其他功能想要在(非常(特定的情况下覆盖:

imbue :如果出于某种原因需要区域设置。 (请记住当前字符编码是区域设置的一部分。

setbuf:允许客户端代码指定缓冲区。 (恕我直言,这是通常不值得打扰,但您可能有特别的要求。

seekoff : 支持寻找。 我从未在任何我的streambuf,所以我不能提供任何超出的信息您可以在标准中阅读。

sync:刷新时调用,应输出缓冲到接收器。 如果您从不打电话给setp(所以没有缓冲区(,您始终处于同步状态,这可能是无操作。 overflowuflow可以调用此一个,或者两者都可以调用一些独立功能。 (关于sync之间的唯一区别uflow是,只有在有以下情况下才会调用uflow一个缓冲区,如果缓冲区为空,则永远不会调用它。 如果客户端代码刷新流,将调用sync

编写自己的流时,除非性能要求否则,我将保持简单,只覆盖overflow.如果性能决定了缓冲区,我通常会将代码放入将缓冲区冲洗到单独的write(address, length)功能,并沿线实施overflowsync之:

int MyStreambuf::overflow( int ch )
{
    if ( pbase() == NULL ) {
        // save one char for next overflow:
        setp( buffer, buffer + bufferSize - 1 );
        if ( ch != EOF ) {
            ch = sputc( ch );
        } else {
            ch = 0;
        }
    } else {
        char* end = pptr();
        if ( ch != EOF ) {
            *end ++ = ch;
        }
        if ( write( pbase(), end - pbase() ) == failed ) {
            ch = EOF;
        } else if ( ch == EOF ) {
            ch = 0;
        }
        setp( buffer, buffer + bufferSize - 1 );
    }
    return ch;
}
int sync()
{
    return (pptr() == pbase()
            || write( pbase(), pptr() - pbase() ) != failed)
        ? 0
        : -1;
}

一般来说,我不会打扰xsputn,但如果你的客户代码输出了很多长字符串,这可能很有用。像这样的东西应该可以解决问题:

streamsize xsputn(char const* p, streamsize n)
{
    streamsize results = 0;
    if ( pptr() == pbase()
            || write( pbase(), pptr() - pbase() ) != failed ) {
        if ( write(p, n) != failed ) {
            results = n;
        }
    }
    setp( buffer, buffer + bufferSize - 1 );
    return results;
}