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-04-10 14:46:02 -0300
commit67f54c1ebeb60be93bfc7ef3caf2e964f045e6b9 (patch)
tree055364c0987c8b58921bc0a93562ca5b96fd6d2a /src
parent07e8390b455b9aa81b7472b401fcaf5dfd48d3c1 (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> (cherry picked from commit f581b041199ba7c825fbffd9110727360d1f2668) Reviewed-by: Ulf Hermann <ulf.hermann@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 6c60e43d80..6110c9a864 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -1369,9 +1369,35 @@ static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &
return nullptr;
}
- auto d = new QCborContainerPrivate;
- d->ref.store(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.store(1);
+ d->elements.reserve(qsizetype(len) << mapShift);
+ }
+ } else {
+ d = new QCborContainerPrivate;
+ d->ref.store(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;
}
@@ -1628,30 +1654,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 1677ed5d65..97bfb3a2dc 100644
--- a/src/corelib/serialization/qcborvalue_p.h
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -390,7 +390,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);
};