我的服务器收到一些请求,编译响应并将其发回。有时响应是一个文件,有时是HTML。因此,我通过以下方式定义响应:
class ResponseData
{
public:
bool operator== (const ResponseData & param) const { return id == param.id; }
public:
RequestIdType id;
RequestType type;
std::vector<char> data;
};
当我编译HTML响应时,我使用std::stringstream
。
std::vector<char> RequestHandler::createResponse( const RequestData * request ) const
{
std::stringstream buffer;
std::vector<char> result;
result.assign( RESPONSE_HEADER, RESPONSE_HEADER + strlen( RESPONSE_HEADER ) );
buffer << "<tr>";
for( auto param : request->paramsMap )
{
buffer << "<tr><td>" << param.first << "</td><td>" << param.second << "</td></tr>\n";
}
buffer << "<\tr>";
DEBUG_LOG_F << buffer.str();
std::string str = buffer.str();
result.insert( result.end(), str.begin(), str.end() );
result.insert( result.end(), RESPONSE_FOOTER, RESPONSE_FOOTER + strlen( RESPONSE_FOOTER ) );
return result;
}
在我看来,将buffer
复制到字符串以将其附加到vector并不是一个好主意。我如何才能更有效地做到这一点?
答案 0 :(得分:3)
您可以使用std::istreambuf_iterator
将字符直接从stringstream
复制到矢量,如下所示:
std::vector<char> sstreamToVector(std::stringstream& src)
{
// make sure that "get" position is at the beginning and "put" is at the end of the stream
src.seekg(0);
src.seekp(0, std::ios::end);
std::vector<char> dst;
dst.reserve(src.tellp());
std::copy(std::istreambuf_iterator<char>(src),
std::istreambuf_iterator<char>(),
std::back_inserter(dst));
return dst;
}
str.tellp()
返回写入流中的字符数(p
代表“放置区域”),因此可用于在缓冲区中分配足够的空间。
答案 1 :(得分:0)
我理解您要避免的事情是char
在容器之间的移动。在这种简单情况下,将所有内容直接转储到result
中并不是很困难:
auto result = accumulate(cbegin(request->paramsMap), cend(request->paramsMap), vector<char>{ '<', 't', 'r', '>', '<', '/', 't', 'r', '>' }, [](auto& init, const auto& i) {
const char start[] = { '<', 't', 'r', '>', '<', 't', 'd', '>' };
const char middle[] = { '<', '/', 't', 'd', '>', '<', 't', 'd', '>' };
const char finish[] = { '<', '/', 't', 'd', '>', '<', '/', 't', 'r', '>' };
init.insert(prev(cend(init), 5U), cbegin(start), cend(start));
init.insert(prev(cend(init), 5U), i.first, next(i.first, strlen(i.first)));
init.insert(prev(cend(init), 5U), cbegin(middle), cend(middle));
init.insert(prev(cend(init), 5U), i.second, next(i.second, strlen(i.second)));
init.insert(prev(cend(init), 5U), cbegin(finish), cend(finsh));
return init;
} );
copy(cbegin(result), cend(result), ostream_iterator<char>{ DEBUG_LOG_F });
result.insert(cbegin(result), RESPONSE_HEADER, next(RESPONSE_HEADER, strlen(RESPONSE_HEADER)));
result.insert(cend(result), RESPONSE_FOOTER, next(RESPONSE_FOOTER, strlen(RESPONSE_FOOTER)));
return result;
答案 2 :(得分:-1)
只需对所有内容使用stringstream
。 joe_chip演示了如何直接从stringstream
复制。
std::stringstream buffer;
buffer << RESPONSE_HEADER;
for( auto param : request->paramsMap )
{
buffer << "<tr><td>" << param.first << "</td><td>" << param.second << "</td></tr>\n";
DEBUG_LOG_F << "<tr><td>" << param.first << "</td><td>" << param.second << "</td></tr>\n";
}
buffer << RESPONSE_FOOTER;
return sstreamToVector(buffer);