summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization/qjsonvalue.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-11-27 11:35:13 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-02-15 17:00:04 -0800
commitc1780165eeca0db6c874866c3184cdaa65542b51 (patch)
tree761227c4a1ce472e4b8c357a2363b0f4abcfd195 /src/corelib/serialization/qjsonvalue.cpp
parentdccd1e87f556c4c88044fa0c8a1c2f4f4c151f59 (diff)
QJsonValueConstRef: optimize to{Int,Integer,Bool,Double,String}()
The CBOR-based implementation from Qt 5.15 simply created a QJsonValue and then called the equivalent function on that result. For integrals and double where the QJsonValue matched the asked type, the cost was minimal anyway. For the other types and when the type didn't match, this resulted in up/down the reference counter in QCborContainerPrivate and an out-of-line call to the destructor. This improves the performance for code like: for (QJsonValue v : array) { if (v.toString() == x) { doSomething(); } } This change propagates the inadviseable behavior of allowing a dereference of the end() reference in concrete() to concreteType() (and unit-tests it) but does not do the same for the toXxx() functions. Doing that causes a dereference of QList's end() iterator, which is UB (asserts false in debug mode). Change-Id: I89446ea06b5742efb194fffd16bb3beccd1098e4 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/serialization/qjsonvalue.cpp')
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp93
1 files changed, 74 insertions, 19 deletions
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index 481ac64f55f..27cad8941ed 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -59,6 +59,29 @@
QT_BEGIN_NAMESPACE
+static QJsonValue::Type convertFromCborType(QCborValue::Type type) noexcept
+{
+ switch (type) {
+ case QCborValue::Null:
+ return QJsonValue::Null;
+ case QCborValue::True:
+ case QCborValue::False:
+ return QJsonValue::Bool;
+ case QCborValue::Double:
+ case QCborValue::Integer:
+ return QJsonValue::Double;
+ case QCborValue::String:
+ return QJsonValue::String;
+ case QCborValue::Array:
+ return QJsonValue::Array;
+ case QCborValue::Map:
+ return QJsonValue::Object;
+ case QCborValue::Undefined:
+ default:
+ return QJsonValue::Undefined;
+ }
+}
+
/*!
\class QJsonValue
\inmodule QtCore
@@ -608,25 +631,7 @@ QVariant QJsonValue::toVariant() const
*/
QJsonValue::Type QJsonValue::type() const
{
- switch (value.type()) {
- case QCborValue::Null:
- return QJsonValue::Null;
- case QCborValue::True:
- case QCborValue::False:
- return QJsonValue::Bool;
- case QCborValue::Double:
- case QCborValue::Integer:
- return QJsonValue::Double;
- case QCborValue::String:
- return QJsonValue::String;
- case QCborValue::Array:
- return QJsonValue::Array;
- case QCborValue::Map:
- return QJsonValue::Object;
- case QCborValue::Undefined:
- default:
- return QJsonValue::Undefined;
- }
+ return convertFromCborType(value.type());
}
/*!
@@ -950,6 +955,56 @@ QJsonObject QJsonValueConstRef::toObject() const
return concrete(*this).toObject();
}
+QJsonValue::Type QJsonValueConstRef::concreteType(QJsonValueConstRef self) noexcept
+{
+ return convertFromCborType(QJsonPrivate::Value::elementHelper(self).type);
+}
+
+bool QJsonValueConstRef::concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ if (e.type == QCborValue::False)
+ return false;
+ if (e.type == QCborValue::True)
+ return true;
+ return defaultValue;
+}
+
+qint64 QJsonValueConstRef::concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ qint64 v = defaultValue;
+ if (e.type == QCborValue::Double) {
+ // convertDoubleTo modifies the output even on returning false
+ if (!convertDoubleTo<qint64>(e.fpvalue(), &v))
+ v = defaultValue;
+ } else if (e.type == QCborValue::Integer) {
+ v = e.value;
+ }
+ if (clamp && qint64(int(v)) != v)
+ return defaultValue;
+ return v;
+}
+
+double QJsonValueConstRef::concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ if (e.type == QCborValue::Double)
+ return e.fpvalue();
+ if (e.type == QCborValue::Integer)
+ return e.value;
+ return defaultValue;
+}
+
+QString QJsonValueConstRef::concreteString(QJsonValueConstRef self, const QString &defaultValue)
+{
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);
+ qsizetype index = QJsonPrivate::Value::indexHelper(self);
+ if (d->elements.at(index).type != QCborValue::String)
+ return defaultValue;
+ return d->stringAt(index);
+}
+
QJsonValue QJsonValueConstRef::concrete(QJsonValueConstRef self) noexcept
{
const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);