summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2020-03-20 18:43:09 -0300
committerThiago Macieira <thiago.macieira@intel.com>2020-03-25 16:22:02 -0300
commitf581b041199ba7c825fbffd9110727360d1f2668 (patch)
treeef7e4478c42ca44b017673d495b4c52f43ae970e /src
parent02d595946faa7a21f6aa4109227f7e90db20ae7a (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')
-rw-r--r--src/corelib/serialization/qcborvalue.cpp56
-rw-r--r--src/corelib/serialization/qcborvalue_p.h1
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);
};