我有:
b
p
是缓冲区,sep
是数据包(新到达的字节),\r\n\r\n
是分隔符序列,例如b + p
。我想在p.begin(), pos
中找到下一个分隔符的位置,然后将范围p
从b
移到b
,而不会增加std::string cc = b + p;
auto cc_pos = std::search(cc.begin(), cc.end(), sep.begin(), sep.end());
b = std::string(cc.begin(), atcc);
if (b.size() > MAX_BYTES)
throw std::runtime_error("packet too large");
if (cc_pos != cc.end())
p = std::string(cc_pos + sep.size(), cc.end());
else
p.clear();
。如果找不到sep,只需附加一切。从逻辑上看,它看起来像这样:
cc
但是我在这里创建了大小为p.size() + b.size()
的临时b
。如何有效地完成(不分配堆内存),如果可能的话,优雅?字符串MAX_BYTES
保留O(nr*np)
,因此插入速度很快,但它永远不会分配更多。
答案 0 :(得分:1)
如果我理解正确,您可以搜索b
的最后 n 个字符,其中 n 的长度为sep
。如果发现sep序列以b
的最后 n 个字符开头,sep
的第二部分可以在p
的开头搜索。< / p>
像
这样的东西int n = sep.size();
int remaining = n;
for (int i = 0; i < sep.size(); i++) {
/* Search for entire sep at end of b
if not found, search for sep minus last char
then minus last 2 chars, 3 chars, and so on
*/
auto it = std::search(b.end() - n - i, b.end(), sep.begin(), sep.end() - i);
if (it != b.end()) {
remaining = i; // number of sep chars to search for in p
break;
}
}
if (remaining > 0) {
std::string sep_sub = sep.substr(n-remaining, remaining);
std::string p_sub = p.substr(0, remaining);
if (sep_sub == p_sub) {
// Found sep split across b and p!
}
}
这应该检查sep
b
和p
之间是否发生sep_sub
吐,而不必连接。唯一使用的额外内存是p_sub
和2 * (sizeof(sep) - 1)
,其组合最多为i
。
这只检查sep是否在b和p之间分割。你仍然需要检查整个sep是否在b或p中。