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