QCborValue: apply a simple optimization to avoid unnecessary allocations

If the map or array is known to be empty, we don't need to allocate a
QCborContainerPrivate.

Change-Id: Ief61acdfbe4d4b5ba1f0fffd15fe212b6a6e77c3
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Thiago Macieira 2020-03-20 18:43:09 -03:00
parent 02d595946f
commit f581b04119
2 changed files with 29 additions and 28 deletions

View File

@ -1445,9 +1445,35 @@ static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &
return nullptr;
}
auto d = new QCborContainerPrivate;
d->ref.storeRelaxed(1);
d->decodeContainerFromCbor(reader, remainingRecursionDepth - 1);
QCborContainerPrivate *d = nullptr;
int mapShift = reader.isMap() ? 1 : 0;
if (reader.isLengthKnown()) {
quint64 len = reader.length();
// Clamp allocation to 1M elements (avoids crashing due to corrupt
// stream or loss of precision when converting from quint64 to
// QVector::size_type).
len = qMin(len, quint64(1024 * 1024 - 1));
if (len) {
d = new QCborContainerPrivate;
d->ref.storeRelaxed(1);
d->elements.reserve(qsizetype(len) << mapShift);
}
} else {
d = new QCborContainerPrivate;
d->ref.storeRelaxed(1);
}
reader.enterContainer();
if (reader.lastError() != QCborError::NoError)
return d;
while (reader.hasNext() && reader.lastError() == QCborError::NoError)
d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
if (reader.lastError() == QCborError::NoError)
reader.leaveContainer();
return d;
}
@ -1637,30 +1663,6 @@ void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader, int r
}
}
void QCborContainerPrivate::decodeContainerFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
{
int mapShift = reader.isMap() ? 1 : 0;
if (reader.isLengthKnown()) {
quint64 len = reader.length();
// Clamp allocation to 1M elements (avoids crashing due to corrupt
// stream or loss of precision when converting from quint64 to
// QVector::size_type).
len = qMin(len, quint64(1024 * 1024 - 1));
elements.reserve(qsizetype(len) << mapShift);
}
reader.enterContainer();
if (reader.lastError() != QCborError::NoError)
return;
while (reader.hasNext() && reader.lastError() == QCborError::NoError)
decodeValueFromCbor(reader, remainingRecursionDepth);
if (reader.lastError() == QCborError::NoError)
reader.leaveContainer();
}
/*!
Creates a QCborValue with byte array value \a ba. The value can later be
retrieved using toByteArray().

View File

@ -406,7 +406,6 @@ public:
}
void decodeValueFromCbor(QCborStreamReader &reader, int remainiingStackDepth);
void decodeContainerFromCbor(QCborStreamReader &reader, int remainingStackDepth);
void decodeStringFromCbor(QCborStreamReader &reader);
static inline void setErrorInReader(QCborStreamReader &reader, QCborError error);
};