我想这就是您正在寻找的 - 一个返回指向其缓冲区的指针的流缓冲区:
#include <iostream>
#include <vector>
#include <string>
class raw_buffer : public std::streambuf
{
public:
raw_buffer(std::ostream& os, int buf_size = 256);
int_type overflow(int_type c) override;
std::streamsize showmanyc() override;
std::streamsize xsputn(const char_type*, std::streamsize) override;
int sync() override;
bool flush();
std::string const& str() const;
private:
std::ostream& os_;
std::vector<char> buffer;
std::string aux;
};
Now str()
很简单。它返回一个指向辅助缓冲区的底层缓冲区的指针:
std::string const& raw_buffer::str() const
{
return aux;
}
其余函数是流缓冲区的常见实现。showmanyc()
应返回辅助缓冲区的大小(aux
只是整个缓冲区的运行总计,buffer
另一方面是施工时指定的尺寸)。
例如,这里是overflow()
,它应该同时更新两个缓冲区,但仍然处理buffer
作为主缓冲区:
raw_buffer::int_type raw_buffer::overflow(raw_buffer::int_type c) override
{
if (os_ && !traits_type::eq_int_type(c, traits_type::eof()))
{
aux += *this->pptr() = traits_type::to_char_type(c);
this->pbump(1);
if (flush())
{
this->pbump(-(this->pptr() - this->pbase()));
this->setp(this->buffer.data(),
this->buffer.data() + this->buffer.size());
return c;
}
}
return traits_type::eof();
}
flush()
用于复制内容buffer
到流(os_
), and sync()
应该被覆盖来调用flush()
too.
xsputn
还需要重写才能写入aux
还有:
std::streamsize raw_buffer::xsputn(const raw_buffer::char_type* str, std::streamsize count) override
{
for (int i = 0; i < count; ++i)
{
if (traits_type::eq_int_type(this->sputc(str[i]), traits_type::eof()))
return i;
else
aux += str[i];
}
return count;
}
现在我们可以将其与自定义流结合起来:
class raw_ostream : private virtual raw_buffer
, public std::ostream
{
public:
raw_ostream(std::ostream& os) : raw_buffer(os)
, std::ostream(this)
{ }
std::string const& str() const
{
return this->raw_buffer::str();
}
std::streamsize count()
{
return this->str().size();
}
};
它可以这样使用:
int main()
{
raw_ostream rostr(std::cout);
rostr << "Hello, World " << 123 << true << false;
auto& buf = rostr.str();
std::cout << buf;
}