QJsonValueRef: optimize the assignment

Inline some content to avoid unnecessary round-trips through
qcborvalue.cpp, qjsonarray.cpp and qjsonobject.cpp.

Unlike the CBOR counterparts, JSON support has this extra functionality
that assigning Undefined causes the item to be removed from the object
(arrays don't have that behavior, they just become null).

And unlike QCborValueRef, we detach on assignment, not on the obtention
of the QJsonValueRef. This is more dangerous, so we may want to revise.

Change-Id: I89446ea06b5742efb194fffd16bb775e9566ca1a
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
This commit is contained in:
Thiago Macieira 2021-11-27 11:28:57 -06:00
parent c1780165ee
commit d263147921
5 changed files with 43 additions and 11 deletions

View File

@ -263,6 +263,7 @@ public:
private: private:
friend class QJsonValue; friend class QJsonValue;
friend class QJsonValueConstRef; friend class QJsonValueConstRef;
friend class QJsonValueRef;
friend class QJsonPrivate::Value; friend class QJsonPrivate::Value;
friend class QJsonDocument; friend class QJsonDocument;
friend class QCborArray; friend class QCborArray;

View File

@ -1428,6 +1428,7 @@ QString QJsonObject::keyAt(qsizetype i) const
return o->stringAt(i * 2); return o->stringAt(i * 2);
} }
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
/*! /*!
\internal \internal
*/ */
@ -1452,6 +1453,7 @@ void QJsonObject::setValueAt(qsizetype i, const QJsonValue &val)
o->replaceAt(2 * i + 1, QCborValue::fromJsonValue(val)); o->replaceAt(2 * i + 1, QCborValue::fromJsonValue(val));
} }
} }
#endif // Qt 7
/*! /*!
\internal \internal

View File

@ -303,8 +303,10 @@ private:
template <typename T> iterator insertImpl(T key, const QJsonValue &value); template <typename T> iterator insertImpl(T key, const QJsonValue &value);
QString keyAt(qsizetype i) const; QString keyAt(qsizetype i) const;
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
QJsonValue valueAt(qsizetype i) const; QJsonValue valueAt(qsizetype i) const;
void setValueAt(qsizetype i, const QJsonValue &val); void setValueAt(qsizetype i, const QJsonValue &val);
#endif
void removeAt(qsizetype i); void removeAt(qsizetype i);
template <typename T> iterator insertAt(qsizetype i, T key, const QJsonValue &val, bool exists); template <typename T> iterator insertAt(qsizetype i, T key, const QJsonValue &val, bool exists);

View File

@ -919,25 +919,49 @@ bool QJsonValue::operator!=(const QJsonValue &other) const
However, they are not explicitly documented here. However, they are not explicitly documented here.
*/ */
void QJsonValueRef::detach()
{
QCborContainerPrivate *d = QJsonPrivate::Value::container(*this);
d = QCborContainerPrivate::detach(d, d->elements.size());
if (is_object)
o->o.reset(d);
else
a->a.reset(d);
}
static QJsonValueRef &assignToRef(QJsonValueRef &ref, const QCborValue &value, bool is_object)
{
QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
qsizetype index = QJsonPrivate::Value::indexHelper(ref);
if (is_object && value.isUndefined()) {
d->removeAt(index);
d->removeAt(index - 1);
} else {
d->replaceAt(index, value);
}
return ref;
}
QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val) QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
{ {
if (is_object) detach();
o->setValueAt(index, val); return assignToRef(*this, QCborValue::fromJsonValue(val), is_object);
else
a->replace(index, val);
return *this;
} }
QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref) QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
{ {
if (is_object) // ### optimize more?
o->setValueAt(index, ref); const QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
else qsizetype index = QJsonPrivate::Value::indexHelper(ref);
a->replace(index, ref);
return *this; if (d == QJsonPrivate::Value::container(*this) &&
index == QJsonPrivate::Value::indexHelper(*this))
return *this; // self assignment
detach();
return assignToRef(*this, d->valueAt(index), is_object);
} }
QVariant QJsonValueConstRef::toVariant() const QVariant QJsonValueConstRef::toVariant() const

View File

@ -263,7 +263,10 @@ public:
private: private:
QJsonValue toValue() const; QJsonValue toValue() const;
#else
private:
#endif // < Qt 7 #endif // < Qt 7
void detach();
}; };
inline QJsonValue QCborValueConstRef::toJsonValue() const inline QJsonValue QCborValueConstRef::toJsonValue() const