diff options
| author | Thiago Macieira <thiago.macieira@intel.com> | 2021-11-27 11:35:13 -0800 |
|---|---|---|
| committer | Thiago Macieira <thiago.macieira@intel.com> | 2022-02-15 17:00:04 -0800 |
| commit | c1780165eeca0db6c874866c3184cdaa65542b51 (patch) | |
| tree | 761227c4a1ce472e4b8c357a2363b0f4abcfd195 /src/corelib/serialization/qjsonvalue.cpp | |
| parent | dccd1e87f556c4c88044fa0c8a1c2f4f4c151f59 (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.cpp | 93 |
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); |
