Dig*_*ers 6 c++ iostream ostream streambuf
我一直在研究创建我自己的ostream以及一个streambuf来处理我的ostream的缓冲区.我实际上大部分工作,我可以插入(<<)到我的流中,并获得字符串没有问题.我通过虚拟函数xsputn来实现这一点.但是,如果我输入(<<)一个浮点数或一个int到流而不是字符串xsputn永远不会被调用.
我已经遍历了代码,我看到流正在调用do_put,然后是f_put,它最终会尝试将float 1字符一次放入缓冲区.我可以让它调用我的虚函数溢出(int c)的实现,如果我让我的缓冲区没有空间,从而得到浮点数和int的数据.
现在问题就在这里,我需要知道何时将float放入缓冲区.换句话说,我需要知道这是什么时候最后一次溢出将被调用为特定值流入.xsputn对我有用的原因是因为我得到了整个值及其长度.所以我可以将它复制到缓冲区然后调用等待缓冲区已满的函数.
我无可否认地滥用了ostream设计,因为我需要缓存输出然后立即为每个输入值(<<)发送它.
无论如何要清楚我会以另一种方式重申我正在拍摄的内容.我很有可能以错误的方式解决这个问题.
我想使用一个继承的ostream和streambuf所以我可以输入值并允许它为我处理我的类型转换,然后我想将这些信息传递给另一个我将句柄传递给streambuf的对象(对于?).该对象有昂贵的i/o所以我不想一次发送数据1个字符.
如果不清楚,请提前抱歉.谢谢你的时间.
Jam*_*nze 16
虽然听起来大致正确,但你所做的事情并不太清楚.只是为了确定:你ostream所做的就是提供方便构造函数来创建和安装你streambuf的析构函数,并且可能是一个rdbuf处理正确类型的缓冲区的实现.假设这是真的:xsputn在你的定义中streambuf纯粹是一种优化.您必须定义的关键功能是overflow.最简单的实现overflow只需要一个字符,然后将其输出到接收器.除此之外的一切都是优化:例如,您可以使用设置缓冲区setp; 如果这样做,那么overflow只有在缓冲区已满或请求刷新时才会调用.在这种情况下,您还必须输出缓冲区(使用pbase和pptr获取地址).(streambuf基类初始化指针以创建0长度缓冲区,因此overflow将为每个字符调用.)在(非常)特定情况下您可能要覆盖的其他函数:
imbue:如果由于某种原因需要语言环境.(请记住,当前字符编码是语言环境的一部分.)
setbuf:允许客户端代码指定缓冲区.(恕我直言,这通常不值得打扰,但你可能有特殊要求.)
seekoff:支持寻求.我从来没有在我streambuf的任何一个中使用过这个,所以除了你在标准中读到的内容之外,我无法提供任何信息.
sync:调用flush时,应将缓冲区中的任何字符输出到接收器.如果你从不打电话setp(所以没有缓冲区),你总是在同步,这可能是一个无操作.
overflow或者uflow可以调用这个,或者两者都可以调用一些单独的函数.(关于sync
和之间的唯一区别uflow是,uflow只有在有缓冲区时才会调用它,如果缓冲区为空,它将永远不会被调用.
sync如果客户端代码刷新了流,它将被调用.)
在编写我自己的流时,除非性能另有说明,否则我会保持简单,只能覆盖overflow.如果性能决定了一个缓冲区,我通常会把代码刷新到一个单独的write(address, length)
函数中,overflow并sync按照以下方式实现:
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;
}
Run Code Online (Sandbox Code Playgroud)
一般来说,我不会打扰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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3613 次 |
| 最近记录: |