如何在不复制或查找的情况下获取 const 字符串流缓冲区的长度?

How can I obtain the length of a const stringstream's buffer without copying or seeking?

本文关键字:字符串 const 缓冲区 获取 情况下 复制 查找      更新时间:2023-10-16

我有一个const std::stringstream,并希望找出其底层字符串缓冲区中有多少字节。

  • 我不能seekg到最后,tellg然后seekg再次开始,因为这些操作都不可用const

  • 我不想获得str().size(),因为str()返回一个副本,这可能不是微不足道的数据量。

我有什么好的选择吗?


(流本身以const的形式呈现给我,只是因为它是另一种类型的成员,并且我收到对该类型对象的const引用。流表示"文档"的内容,其封装对象表示 CGI 响应,我正在尝试从 operator<<(std::ostream&, const cgi_response&) 中生成准确的 Content-Length HTTP 标头行。

我对流缓冲区从来都不是很满意,但这似乎对我有用:

#include <iostream>
#include <sstream>
std::stringstream::pos_type size_of_stream(const std::stringstream& ss)
{
    std::streambuf* buf = ss.rdbuf();
    // Get the current position so we can restore it later
    std::stringstream::pos_type original = buf->pubseekoff(0, ss.cur, ss.out);
    // Seek to end and get the position
    std::stringstream::pos_type end = buf->pubseekoff(0, ss.end, ss.out);
    // Restore the position
    buf->pubseekpos(original, ss.out);
    return end;
}
int main()
{
    std::stringstream ss;
    ss << "Hello";
    ss << ' ';
    ss << "World";
    ss << 42;
    std::cout << size_of_stream(ss) << std::endl;
    // Make sure the output string is still the same
    ss << "nnew line";
    std::cout << ss.str() << std::endl;
    std::string str;
    ss >> str;
    std::cout << str << std::endl;
}

关键是rdbuf() const但返回一个非常量缓冲区,然后可以使用该缓冲区进行查找。

如果您想知道剩余的可用输入大小:

#include <iostream>
#include <sstream>
std::size_t input_available(const std::stringstream& s)
{
    std::streambuf* buf = s.rdbuf();
    std::streampos pos = buf->pubseekoff(0, std::ios_base::cur, std::ios_base::in);
    std::streampos end = buf->pubseekoff(0, std::ios_base::end, std::ios_base::in);
    buf->pubseekpos(pos, std::ios_base::in);
    return end - pos;
}
int main()
{
    std::stringstream stream;
    // Output
    std::cout << input_available(stream) << std::endl; // 0
    stream << "123 ";
    std::cout << input_available(stream) << std::endl; // 4
    stream << "567";
    std::cout << input_available(stream) << std::endl; // 7
    // Input
    std::string s;
    stream >> s;
    std::cout << input_available(stream) << std::endl; // 4
    stream >> s;
    std::cout << input_available(stream) << std::endl; // 0
}

这类似于@Cornstalks解决方案,但正确定位了输入序列。

这应该:)工作)

#include <iostream>
#include <sstream>
#include <boost/move/move.hpp>
int main()
{
    const std::stringstream ss("hello");
    std::cout << boost::move(ss).str().size();
}
相关文章: