From 2bb44414ff456873c885391e4a03afb67e7306da Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 19 May 2018 14:58:43 -0700 Subject: QCborArray & Map: implement efficient take() / extract() Questions: 1) should QCborMap::extract return value_type (a pair) instead of just the value? 2) should the both return the iterator to the next element too, like erase()? Change-Id: I052407b777ec43f78378fffd15302a9c14468db3 Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/serialization/qcborvalue_p.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'src/corelib/serialization/qcborvalue_p.h') diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h index c80abd68f5..eb6fe09147 100644 --- a/src/corelib/serialization/qcborvalue_p.h +++ b/src/corelib/serialization/qcborvalue_p.h @@ -124,6 +124,8 @@ class QCborContainerPrivate : public QSharedData ~QCborContainerPrivate(); public: + enum ContainerDisposition { CopyContainer, MoveContainer }; + QByteArray::size_type usedData = 0; QByteArray data; QVector elements; @@ -275,12 +277,13 @@ public: return data->toUtf8String(); } - static QCborValue makeValue(QCborValue::Type type, qint64 n, QCborContainerPrivate *d = nullptr) + static QCborValue makeValue(QCborValue::Type type, qint64 n, QCborContainerPrivate *d = nullptr, + ContainerDisposition disp = CopyContainer) { QCborValue result(type); result.n = n; result.container = d; - if (d) + if (d && disp == CopyContainer) d->ref.ref(); return result; } @@ -300,6 +303,24 @@ public: } return makeValue(e.type, e.value); } + QCborValue extractAt_complex(QtCbor::Element e); + QCborValue extractAt(qsizetype idx) + { + QtCbor::Element e; + qSwap(e, elements[idx]); + + if (e.flags & QtCbor::Element::IsContainer) { + if (e.type == QCborValue::Tag && e.container->elements.size() != 2) { + // invalid tags can be created due to incomplete parsing + e.container->deref(); + return makeValue(QCborValue::Invalid, 0, nullptr); + } + return makeValue(e.type, -1, e.container, MoveContainer); + } else if (e.flags & QtCbor::Element::HasByteData) { + return extractAt_complex(e); + } + return makeValue(e.type, e.value); + } static QtCbor::Element elementFromValue(const QCborValue &value) { -- cgit v1.2.3