From f4d49910be81419cd951c602cca34f368b179652 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Nov 2021 10:33:16 -0800 Subject: [PATCH] QCborValueConstRef: optimize to{Integer,Bool,Double,String,ByteArray}() The initial implementation from Qt 5.13 simply created a QCborValue and then called the equivalent function on that result. For integrals and double where the QCborValue 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 (QCborValue v : array) { if (v.toString() == x) { doSomething(); } } Change-Id: I5e52dc5b093c43a3b678fffd16b6022da4e2d446 Reviewed-by: Marc Mutz Reviewed-by: Edward Welbourne --- src/corelib/serialization/qcborvalue.cpp | 46 ++++++++++++++++++++++++ src/corelib/serialization/qcborvalue.h | 20 ++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 8fff1c2940..eaa9369abc 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2635,6 +2635,52 @@ void QCborValueRef::assign(QCborValueRef that, const QCborValueRef other) that = other.concrete(); } +bool QCborValueConstRef::concreteBoolean(QCborValueConstRef self, bool defaultValue) noexcept +{ + QtCbor::Element e = self.d->elements.at(self.i); + if (e.type != QCborValue::False && e.type != QCborValue::True) + return defaultValue; + return e.type == QCborValue::True; +} + +double QCborValueConstRef::concreteDouble(QCborValueConstRef self, double defaultValue) noexcept +{ + QtCbor::Element e = self.d->elements.at(self.i); + if (e.type == QCborValue::Integer) + return e.value; + if (e.type != QCborValue::Double) + return defaultValue; + return e.fpvalue(); +} + +qint64 QCborValueConstRef::concreteIntegral(QCborValueConstRef self, qint64 defaultValue) noexcept +{ + QtCbor::Element e = self.d->elements.at(self.i); + QCborValue::Type t = e.type; + if (t == QCborValue::Double) + return e.fpvalue(); + if (t != QCborValue::Integer) + return defaultValue; + return e.value; +} + +QByteArray QCborValueConstRef::concreteByteArray(QCborValueConstRef self, + const QByteArray &defaultValue) +{ + QtCbor::Element e = self.d->elements.at(self.i); + if (e.type != QCborValue::ByteArray) + return defaultValue; + return self.d->byteArrayAt(self.i); +} + +QString QCborValueConstRef::concreteString(QCborValueConstRef self, const QString &defaultValue) +{ + QtCbor::Element e = self.d->elements.at(self.i); + if (e.type != QCborValue::String) + return defaultValue; + return self.d->stringAt(self.i); +} + QCborValue QCborValueConstRef::concrete(QCborValueConstRef self) noexcept { return self.d->valueAt(self.i); diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h index d7b5ec68aa..39010210d9 100644 --- a/src/corelib/serialization/qcborvalue.h +++ b/src/corelib/serialization/qcborvalue.h @@ -445,6 +445,16 @@ protected: static Q_CORE_EXPORT QCborValue concrete(QCborValueConstRef that) noexcept; static Q_CORE_EXPORT QCborValue::Type concreteType(QCborValueConstRef that) noexcept Q_DECL_PURE_FUNCTION; + static Q_CORE_EXPORT bool + concreteBoolean(QCborValueConstRef that, bool defaultValue) noexcept Q_DECL_PURE_FUNCTION; + static Q_CORE_EXPORT double + concreteDouble(QCborValueConstRef that, double defaultValue) noexcept Q_DECL_PURE_FUNCTION; + static Q_CORE_EXPORT qint64 + concreteIntegral(QCborValueConstRef that, qint64 defaultValue) noexcept Q_DECL_PURE_FUNCTION; + static Q_CORE_EXPORT QByteArray + concreteByteArray(QCborValueConstRef that, const QByteArray &defaultValue); + static Q_CORE_EXPORT QString + concreteString(QCborValueConstRef that, const QString &defaultValue); constexpr QCborValueConstRef() : d(nullptr), i(0) {} // this will actually be invalid constexpr QCborValueConstRef(QCborContainerPrivate *dd, qsizetype ii) @@ -513,16 +523,16 @@ public: { return concrete().taggedValue(defaultValue); } qint64 toInteger(qint64 defaultValue = 0) const - { return concrete().toInteger(defaultValue); } + { return concreteIntegral(*this, defaultValue); } bool toBool(bool defaultValue = false) const - { return concrete().toBool(defaultValue); } + { return concreteBoolean(*this, defaultValue); } double toDouble(double defaultValue = 0) const - { return concrete().toDouble(defaultValue); } + { return concreteDouble(*this, defaultValue); } QByteArray toByteArray(const QByteArray &defaultValue = {}) const - { return concrete().toByteArray(defaultValue); } + { return concreteByteArray(*this, defaultValue); } QString toString(const QString &defaultValue = {}) const - { return concrete().toString(defaultValue); } + { return concreteString(*this, defaultValue); } QDateTime toDateTime(const QDateTime &defaultValue = {}) const { return concrete().toDateTime(defaultValue); } #ifndef QT_BOOTSTRAPPED