Port QResourceRoot::mappingRootSubdir() to QStringSplitter

The code here performs a std::mismatch() on the normalized parts of
'root' and 'path', returning whether 'path' is a prefix of 'root'. If
'path' is a proper prefix of 'root', returns the first 'root' part
after 'path', in '*match'.

Instead of using QString::splitRef(), perform the splitting as we go,
using this class' own tool, QStringSplitter.

The goal here is to avoid the heap allocation caused by the QVector
return of splitRef(), of course. But even though using QStringSplitter
means the splitting is now purely inline, text size in optimized GCC 7
Linux AMD64 builds increases by only 24B.

Change-Id: I396cc6a30306940220c9e783c31506e6ac17b784
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Marc Mutz 2017-03-29 22:06:34 +02:00
parent 4fd5273f61
commit 0c8b5446d4

View File

@ -833,24 +833,24 @@ QStringList QResourceRoot::children(int node) const
bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const
{
const QString root = mappingRoot();
if(!root.isEmpty()) {
const QVector<QStringRef> root_segments = root.splitRef(QLatin1Char('/'), QString::SkipEmptyParts),
path_segments = path.splitRef(QLatin1Char('/'), QString::SkipEmptyParts);
if(path_segments.size() <= root_segments.size()) {
int matched = 0;
for(int i = 0; i < path_segments.size(); ++i) {
if(root_segments[i] != path_segments[i])
break;
++matched;
}
if(matched == path_segments.size()) {
if(match && root_segments.size() > matched)
*match = root_segments.at(matched).toString();
return true;
}
if (root.isEmpty())
return false;
QStringSplitter rootIt(root);
QStringSplitter pathIt(path);
while (rootIt.hasNext()) {
if (pathIt.hasNext()) {
if (rootIt.next() != pathIt.next()) // mismatch
return false;
} else {
// end of path, but not of root:
if (match)
*match = rootIt.next().toString();
return true;
}
}
return false;
// end of root
return !pathIt.hasNext();
}
Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,