不太清楚你在做什么,虽然听起来很粗略
正确的。可以肯定的是:您的所有ostream 所做的只是提供
方便的构造函数来创建和安装你的streambuf,
析构函数,可能是rdbuf 的实现
处理正确类型的缓冲区。假设这是真的:
在 streambuf 中定义 xsputn 纯粹是一种优化。
您必须定义的关键函数是overflow。最简单的
overflow 的实现只需要一个字符,并且
将其输出到接收器。除此之外的一切都是优化:
例如,您可以使用setp 设置缓冲区;如果你这样做
这个,然后overflow 只会在缓冲区被调用时
已满,或已请求刷新。在这种情况下,您必须
输出缓冲区(使用pbase 和pptr 来获取
地址)。 (streambuf 基类初始化
创建 0 长度缓冲区的指针,因此 overflow 将是
为每个字符调用。)您可能会使用的其他功能
想要在(非常)特定的情况下覆盖:
imbue: 如果你出于某种原因需要语言环境。 (请记住
当前字符编码是语言环境的一部分。)
setbuf:允许客户端代码指定一个缓冲区。 (恕我直言,这是
通常不值得费心,但你可能有特别的
要求。)
seekoff:支持求。我从来没有用过这个
我的streambufs,所以我不能提供任何信息
你可以阅读标准。
sync: 在刷新时调用,应该输出任何字符
缓冲到水槽。如果你从不打电话给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;
}
一般来说,我不会打扰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;
}