QFactoryLoader: rewrite parse() using the new iterateInPluginMetaData()

This doesn't simplify the actual parsing or make it any faster, but does
merge the validation code so we only have it in one place.

Change-Id: I8bd6bb457b9c42218247fffd1797543bec9cfbec
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
bb10
Thiago Macieira 2023-11-13 16:00:00 -08:00
parent 4a432a7617
commit 90df0f4806
1 changed files with 35 additions and 21 deletions

View File

@ -62,7 +62,8 @@ struct QFactoryLoaderIidSearch
{
QLatin1StringView iid;
bool matchesIid = false;
QFactoryLoaderIidSearch(QLatin1StringView iid) : iid(iid) {}
QFactoryLoaderIidSearch(QLatin1StringView iid) : iid(iid)
{ Q_ASSERT(!iid.isEmpty()); }
static QString readString(QCborStreamReader &reader)
{
@ -93,7 +94,7 @@ struct QFactoryLoaderIidSearch
matchesIid = (readString(reader) == iid);
return IterationResult::FinishedSearch;
}
IterationResult::Result operator()(const QCborValue &, QCborStreamReader &reader)
IterationResult::Result operator()(const QString &, QCborStreamReader &reader)
{
return skip(reader);
}
@ -129,11 +130,13 @@ template <typename F> static IterationResult iterateInPluginMetaData(QByteArrayV
if (!reader.next())
return reader.lastError();
r = f(key, reader);
} else {
QCborValue key = QCborValue::fromCbor(reader);
if (key.isInvalid())
} else if (reader.isString()) {
QString key = readString(reader);
if (key.isNull())
return reader.lastError();
r = f(key, reader);
} else {
return IterationResult::InvalidTopLevelItem;
}
if (QCborError e = reader.lastError())
@ -156,24 +159,35 @@ static bool isIidMatch(QByteArrayView raw, QLatin1StringView iid)
bool QPluginParsedMetaData::parse(QByteArrayView raw)
{
QPluginMetaData::Header header;
Q_ASSERT(raw.size() >= qsizetype(sizeof(header)));
memcpy(&header, raw.data(), sizeof(header));
if (Q_UNLIKELY(header.version > QPluginMetaData::CurrentMetaDataVersion))
QCborMap map;
auto r = iterateInPluginMetaData(raw, [&](const auto &key, QCborStreamReader &reader) {
QCborValue item = QCborValue::fromCbor(reader);
if (item.isInvalid())
return IterationResult::ParsingError;
if constexpr (std::is_enum_v<std::decay_t<decltype(key)>>)
map[int(key)] = item;
else
map[key] = item;
return IterationResult::ContinueSearch;
});
switch (r.result) {
case IterationResult::FinishedSearch:
case IterationResult::ContinueSearch:
break;
// parse errors
case IterationResult::ParsingError:
return setError(QFactoryLoader::tr("Metadata parsing error: %1").arg(r.error.toString()));
case IterationResult::InvalidMetaDataVersion:
return setError(QFactoryLoader::tr("Invalid metadata version"));
// use fromRawData to keep QCborStreamReader from copying
raw = raw.sliced(sizeof(header));
QByteArray ba = QByteArray::fromRawData(raw.data(), raw.size());
QCborParserError err;
QCborValue metadata = QCborValue::fromCbor(ba, &err);
if (err.error != QCborError::NoError)
return setError(QFactoryLoader::tr("Metadata parsing error: %1").arg(err.error.toString()));
if (!metadata.isMap())
case IterationResult::InvalidTopLevelItem:
case IterationResult::InvalidHeaderItem:
return setError(QFactoryLoader::tr("Unexpected metadata contents"));
QCborMap map = metadata.toMap();
metadata = {};
}
// header was validated
auto header = qFromUnaligned<QPluginMetaData::Header>(raw.data());
DecodedArchRequirements archReq =
header.version == 0 ? decodeVersion0ArchRequirements(header.plugin_arch_requirements)