diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2020-03-20 18:43:09 -0300 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2020-03-25 16:22:02 -0300 |
commit | f581b041199ba7c825fbffd9110727360d1f2668 (patch) | |
tree | ef7e4478c42ca44b017673d495b4c52f43ae970e /src/corelib | |
parent | 02d595946faa7a21f6aa4109227f7e90db20ae7a (diff) |
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>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/serialization/qcborvalue.cpp | 56 | ||||
-rw-r--r-- | src/corelib/serialization/qcborvalue_p.h | 1 |
2 files changed, 29 insertions, 28 deletions
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 23b4a15c0c..f4ceba3836 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -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(). diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h index 2358626541..041a20e746 100644 --- a/src/corelib/serialization/qcborvalue_p.h +++ b/src/corelib/serialization/qcborvalue_p.h @@ -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); }; |