Rework StringVector to have a single underlying string

This is meant to reduce lots of small allocations and instead have
pointers into the single string for the various tokens instead.

This has a few requirements, though:

1) It's no longer OK to modify the tokens, changing their length would
invalidate the start/length of other tokens. Rework
DocumentBroker::load() to avoid such mutation.

2) The iterators no longer expose zero-terminated strings, so
Poco::cat() doesn't work anymore: add an own cat() instead and use that
in e.g. ChildSession. The own cat() has the benefit that it won't read
past the end of the array if the begin index is out of bounds to add
more safety.

(This nicely works towards killing Poco usage in general.)

3) If zero-terminated strings for all individual tokens is needed, a
copy has to be made, as done in spawnProcess().

(For all of these requirements, the build fails if there are problems.)

Change-Id: Iea40e4400e630b2d669f5c72aea85cb40edf9a2c
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/89711
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
This commit is contained in:
Miklos Vajna
2020-02-28 14:51:22 +01:00
parent b8bd1990aa
commit 547f9ea731
15 changed files with 178 additions and 71 deletions

View File

@ -11,35 +11,79 @@
StringVector::StringVector() = default;
StringVector::StringVector(const std::vector<std::string>& vector) { _vector = vector; }
StringVector::StringVector(const std::string& string, const std::vector<StringToken>& tokens)
: _string(string),
_tokens(tokens)
{
}
std::string StringVector::operator[](size_t index) const
{
if (index >= _vector.size())
if (index >= _tokens.size())
{
return std::string();
}
return _vector[index];
const StringToken& token = _tokens[index];
return _string.substr(token._index, token._length);
}
size_t StringVector::size() const { return _vector.size(); }
size_t StringVector::size() const { return _tokens.size(); }
bool StringVector::empty() const { return _vector.empty(); }
bool StringVector::empty() const { return _tokens.empty(); }
std::vector<std::string>::const_iterator StringVector::begin() const { return _vector.begin(); }
std::vector<StringToken>::const_iterator StringVector::begin() const { return _tokens.begin(); }
std::vector<std::string>::iterator StringVector::begin() { return _vector.begin(); }
std::vector<StringToken>::iterator StringVector::begin() { return _tokens.begin(); }
std::vector<std::string>::const_iterator StringVector::end() const { return _vector.end(); }
std::vector<StringToken>::const_iterator StringVector::end() const { return _tokens.end(); }
std::vector<std::string>::iterator StringVector::end() { return _vector.end(); }
std::vector<StringToken>::iterator StringVector::end() { return _tokens.end(); }
std::vector<std::string>::iterator StringVector::erase(std::vector<std::string>::const_iterator it)
std::vector<StringToken>::iterator StringVector::erase(std::vector<StringToken>::const_iterator it)
{
return _vector.erase(it);
return _tokens.erase(it);
}
void StringVector::push_back(const std::string& string) { _vector.push_back(string); }
void StringVector::push_back(const std::string& string)
{
StringToken token;
token._index = _string.length();
token._length = string.length();
_tokens.push_back(token);
_string += string;
}
std::string StringVector::getParam(const StringToken& token) const
{
return _string.substr(token._index, token._length);
}
std::string StringVector::cat(const std::string& separator, size_t begin) const
{
std::string ret;
bool first = true;
if (begin >= _tokens.size())
{
return ret;
}
for (auto it = _tokens.begin() + begin; it != _tokens.end(); ++it)
{
if (first)
{
first = false;
}
else
{
ret += separator;
}
ret += getParam(*it);
}
return ret;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */