用xsputn和溢出继承ostream和streambuf问题 [英] inheriting ostream and streambuf problem with xsputn and overflow
问题描述
我一直在研究创建自己的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
仅在缓冲区为
已满,或要求冲洗.在这种情况下,您必须
以及输出缓冲区(使用pbase
和pptr
来获取
地址). (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 streambuf
s, so I can't give any information beyond what
you could read in the standard.
sync
:在刷新时调用,应在
缓冲到水槽.如果您从不致电setp
(因此没有
缓冲区),则您始终处于同步状态,这可以是空操作.
overflow
或uflow
可以叫这一个,或者两个都可以叫一些
单独的功能. (关于sync
并且uflow
是uflow
仅在存在以下情况时才会被调用
一个缓冲区,如果缓冲区为空,它将永远不会被调用.
如果客户端代码刷新了流,则会调用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)
函数,并沿线实现overflow
和sync
的:
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屋!