用xsputn和溢出继承ostream和streambuf问题 [英] inheriting ostream and streambuf problem with xsputn and overflow

查看:140
本文介绍了用xsputn和溢出继承ostream和streambuf问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究创建自己的ostream以及与此相关的streambuf来处理我的ostream的缓冲区.实际上,大多数功能都可以正常工作,我可以将(<<)插入流中并毫无问题地获取字符串.我通过隐含虚函数xsputn来做到这一点.但是,如果我在流中输入(<<)浮点数或int而不是字符串xsputn,则永远不会调用它.

I have been doing research on creating my own ostream and along with that a streambuf to handle the buffer for my ostream. I actually have most of it working, I can insert (<<) into my stream and get strings no problem. I do this by implimenting the virtual function xsputn. However if I input (<<) a float or an int to the stream instead of a string xsputn never gets called.

我已经遍历了代码,看到流正在调用do_put,然后是f_put,该f_put最终尝试一次将float 1字符一次放入缓冲区.如果我的缓冲区没有空间,从而可以获取浮点数和int的数据,则可以调用它来实现我的虚函数的实现(int c).

I have walked through the code and I see that the stream is calling do_put, then f_put which eventually tries to put the float 1 character at a time into the buffer. I can get it to call my implementation of the virtual function overflow(int c) if I leave my buffer with no space and thereby get the data for the float and the int.

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

Now here is the problem, I need to know when the float is done being put into the buffer. Or to put it another way, I need to know when this is the last time overflow will be called for a particular value being streamed in. The reason xsputn works for me is because I get the whole value up front and its length. So i can copy it into the buffer then call out to the function waiting for the buffer to be full.

我确实在滥用ostream设计,因为我需要缓存输出,然后针对每个输入的值(<<)一次全部发送.

I am admittedly abusing the ostream design in that I need to cache the output then send it all at once for each inputted value (<<).

无论如何要明确一点,我将以另一种方式重申我要拍摄的内容.我很有可能会以错误的方式去做.

Anyways to be clear I will restate what I am shooting for in another way. There is a very good chance I am just going about it the wrong way.

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

I want to use an inherited ostream and streambuf so I can input values into it and allow it to handle my type conversion for me, then I want to ferry that information off to another object that I am passing a handle down to the streambuf to (for?). That object has expensive i/o so I dont want to send the data 1 char at a time.

如果不清楚,请提前抱歉.并感谢您的宝贵时间.

Sorry in advance if this is unclear. And thank you for your time.

推荐答案

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

It's not too clear what you're doing, although it sounds roughly right. Just to be sure: all your ostream does is provide convenience constructors to create and install your streambuf, a destructor, and possibly an implementation of rdbuf to handle buffers of the right type. Supposing that's true: defining xsputn in your streambuf is purely an optimization. The key function you have to define is overflow. The simplest implementation of overflow just takes a single character, and outputs it to the sink. Everything beyond that is optimization: you can, for example, set up a buffer using setp; if you do this, then overflow will only be called when the buffer is full, or a flush was requested. In this case, you'll have to output buffer as well (use pbase and pptr to get the addresses). (The streambuf base class initializes the pointers to create a 0 length buffer, so overflow will be called for every character.) Other functions which you might want to override in (very) specific cases:

imbue:如果出于某些原因需要语言环境. (请记住 当前的字符编码是语言环境的一部分.)

imbue: If you need the locale for some reason. (Remember that the current character encoding is part of the locale.)

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

setbuf: To allow client code to specify a buffer. (IMHO, it's usually not worth the bother, but you may have special requirements.)

seekoff:支持查找.我从来没有用过 我的streambuf,因此我无法提供任何其他信息 您可以阅读标准.

seekoff: Support for seeking. I've never used this in any of my streambufs, so I can't give any information beyond what you could read in the standard.

sync:在刷新时调用,应在 缓冲到水槽.如果您从不致电setp(因此没有 缓冲区),则您始终处于同步状态,这可以是空操作. overflowuflow可以叫这一个,或者两个都可以叫一些 单独的功能. (关于sync 并且uflowuflow仅在存在以下情况时才会被调用 一个缓冲区,如果缓冲区为空,它将永远不会被调用. 如果客户端代码刷新了流,则会调用sync.

sync: Called on flush, should output any characters in the buffer to the sink. If you never call setp (so there's no buffer), you're always in sync, and this can be a no-op. overflow or uflow can call this one, or both can call some separate function. (About the only difference between sync and uflow is that uflow will only be called if there is a buffer, and it will never be called if the buffer is empty. sync will be called if the client code flushes the stream.)

在编写自己的流时,除非性能要求 否则,我将使其保持简单,仅覆盖overflow. 如果性能需要缓冲,我通常会将代码放到 将缓冲区刷新到单独的write(address, length) 函数,并沿线实现overflowsync 的:

When writing my own streams, unless performance dictates otherwise, I'll keep it simple, and only override overflow. If performance dictates a buffer, I'll usually put the code to flush the buffer into a separate write(address, length) function, and implement overflow and sync along the lines of:

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,但是如果您的客户 代码输出很多长字符串,这可能很有用. 这样的事情应该可以解决问题:

Generally, I'll not bother with xsputn, but if your client code is outputting a lot of long strings, it could be useful. Something like this should do the trick:

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

这篇关于用xsputn和溢出继承ostream和streambuf问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆