QCborArray & Map: implement move semantics
There isn't a lot of efficiency gain, since QCborValue was already refcounted. This saves two atomic operations and an out-of-line call. In the case of QCborValueRef (which includes QCborMap), because we reset the container pointer in inline code, the call to QCborValue::dispose() is also suppressed. Change-Id: Icc2c231dc2c44abdb087fffd1533eaba7a9c70fa Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>bb10
parent
fddf09363e
commit
514972544a
|
|
@ -298,6 +298,9 @@ QCborValue QCborArray::at(qsizetype i) const
|
|||
*/
|
||||
|
||||
/*!
|
||||
\fn void QCborArray::insert(qsizetype i, const QCborValue &value)
|
||||
\fn void QCborArray::insert(qsizetype i, QCborValue &&value)
|
||||
|
||||
Inserts \a value into the array at position \a i in this array. The array
|
||||
must have at least \a i elements before the insertion.
|
||||
|
||||
|
|
@ -313,6 +316,16 @@ void QCborArray::insert(qsizetype i, const QCborValue &value)
|
|||
d->insertAt(i, value);
|
||||
}
|
||||
|
||||
void QCborArray::insert(qsizetype i, QCborValue &&value)
|
||||
{
|
||||
Q_ASSERT(size_t(i) <= size_t(size()) || i == -1);
|
||||
if (i < 0)
|
||||
i = size();
|
||||
detach(qMax(i + 1, size()));
|
||||
d->insertAt(i, value, QCborContainerPrivate::MoveContainer);
|
||||
QCborContainerPrivate::resetValue(value);
|
||||
}
|
||||
|
||||
/*!
|
||||
Extracts a value from the array at the position indicated by iterator \a it
|
||||
and returns the value so extracted.
|
||||
|
|
@ -330,6 +343,7 @@ QCborValue QCborArray::extract(iterator it)
|
|||
|
||||
/*!
|
||||
\fn void QCborArray::prepend(const QCborValue &value)
|
||||
\fn void QCborArray::prepend(QCborValue &&value)
|
||||
|
||||
Prepends \a value into the array before any other elements it may already
|
||||
contain.
|
||||
|
|
@ -340,6 +354,7 @@ QCborValue QCborArray::extract(iterator it)
|
|||
|
||||
/*!
|
||||
\fn void QCborArray::append(const QCborValue &value)
|
||||
\fn void QCborArray::append(QCborValue &&value)
|
||||
|
||||
Appends \a value into the array after all other elements it may already
|
||||
contain.
|
||||
|
|
|
|||
|
|
@ -190,8 +190,11 @@ public:
|
|||
QCborValueRef operator[](qsizetype i) { Q_ASSERT(i < size()); return begin()[i]; }
|
||||
|
||||
void insert(qsizetype i, const QCborValue &value);
|
||||
void insert(qsizetype i, QCborValue &&value);
|
||||
void prepend(const QCborValue &value) { insert(0, value); }
|
||||
void prepend(QCborValue &&value) { insert(0, std::move(value)); }
|
||||
void append(const QCborValue &value) { insert(-1, value); }
|
||||
void append(QCborValue &&value) { insert(-1, std::move(value)); }
|
||||
QCborValue extract(Iterator it);
|
||||
void removeAt(qsizetype i);
|
||||
QCborValue takeAt(qsizetype i) { Q_ASSERT(i < size()); return extract(begin() + i); }
|
||||
|
|
|
|||
|
|
@ -1053,7 +1053,12 @@ QCborContainerPrivate *QCborContainerPrivate::detach(QCborContainerPrivate *d, q
|
|||
return d;
|
||||
}
|
||||
|
||||
void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &value)
|
||||
// Copies or moves \a value into element at position \a e. If \a disp is
|
||||
// CopyContainer, then this function increases the reference count of the
|
||||
// container, but otherwise leaves it unmodified. If \a disp is MoveContainer,
|
||||
// then it transfers ownership (move semantics) and the caller must set
|
||||
// value.container back to nullptr.
|
||||
void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &value, ContainerDisposition disp)
|
||||
{
|
||||
if (value.n < 0) {
|
||||
// This QCborValue is an array, map, or tagged value (container points
|
||||
|
|
@ -1062,14 +1067,18 @@ void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &valu
|
|||
// detect self-assignment
|
||||
if (Q_UNLIKELY(this == value.container)) {
|
||||
Q_ASSERT(ref.load() >= 2);
|
||||
if (disp == MoveContainer)
|
||||
ref.deref(); // not deref() because it can't drop to 0
|
||||
QCborContainerPrivate *d = QCborContainerPrivate::clone(this);
|
||||
d->elements.detach();
|
||||
d->ref.store(1);
|
||||
e.container = d;
|
||||
} else {
|
||||
e.container = value.container;
|
||||
if (disp == CopyContainer)
|
||||
e.container->ref.ref();
|
||||
}
|
||||
|
||||
e.container->ref.ref();
|
||||
e.type = value.type();
|
||||
e.flags = Element::IsContainer;
|
||||
} else {
|
||||
|
|
@ -1079,6 +1088,9 @@ void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &valu
|
|||
// Copy string data, if any
|
||||
if (const ByteData *b = value.container->byteData(value.n))
|
||||
e.value = addByteData(b->byte(), b->len);
|
||||
|
||||
if (disp == MoveContainer)
|
||||
value.container->deref();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1847,6 +1859,9 @@ QCborValue::QCborValue(QLatin1String s)
|
|||
}
|
||||
|
||||
/*!
|
||||
\fn QCborValue::QCborValue(const QCborArray &a)
|
||||
\fn QCborValue::QCborValue(QCborArray &&a)
|
||||
|
||||
Creates a QCborValue with the array \a a. The array can later be retrieved
|
||||
using toArray().
|
||||
|
||||
|
|
@ -1860,6 +1875,9 @@ QCborValue::QCborValue(const QCborArray &a)
|
|||
}
|
||||
|
||||
/*!
|
||||
\fn QCborValue::QCborValue(const QCborMap &m)
|
||||
\fn QCborValue::QCborValue(QCborMap &&m)
|
||||
|
||||
Creates a QCborValue with the map \a m. The map can later be retrieved
|
||||
using toMap().
|
||||
|
||||
|
|
@ -2526,16 +2544,20 @@ void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOption
|
|||
concrete().toCbor(writer, opt);
|
||||
}
|
||||
|
||||
QCborValueRef &QCborValueRef::operator=(const QCborValue &other)
|
||||
void QCborValueRef::assign(QCborValueRef that, const QCborValue &other)
|
||||
{
|
||||
d->replaceAt(i, other);
|
||||
return *this;
|
||||
that.d->replaceAt(that.i, other);
|
||||
}
|
||||
|
||||
QCborValueRef &QCborValueRef::operator=(const QCborValueRef &other)
|
||||
void QCborValueRef::assign(QCborValueRef that, QCborValue &&other)
|
||||
{
|
||||
that.d->replaceAt(that.i, other, QCborContainerPrivate::MoveContainer);
|
||||
}
|
||||
|
||||
void QCborValueRef::assign(QCborValueRef that, const QCborValueRef other)
|
||||
{
|
||||
// ### optimize?
|
||||
return *this = other.concrete();
|
||||
assign(that, other.concrete());
|
||||
}
|
||||
|
||||
QCborValue QCborValueRef::concrete(QCborValueRef self) Q_DECL_NOTHROW
|
||||
|
|
|
|||
|
|
@ -323,8 +323,14 @@ class Q_CORE_EXPORT QCborValueRef
|
|||
public:
|
||||
operator QCborValue() const { return concrete(); }
|
||||
|
||||
QCborValueRef &operator=(const QCborValue &other);
|
||||
QCborValueRef &operator=(const QCborValueRef &other);
|
||||
QCborValueRef(const QCborValueRef &) Q_DECL_NOTHROW = default;
|
||||
QCborValueRef(QCborValueRef &&) Q_DECL_NOTHROW = default;
|
||||
QCborValueRef &operator=(const QCborValue &other)
|
||||
{ assign(*this, other); return *this; }
|
||||
QCborValueRef &operator=(QCborValue &&other)
|
||||
{ assign(*this, std::move(other)); other.container = nullptr; return *this; }
|
||||
QCborValueRef &operator=(const QCborValueRef &other)
|
||||
{ assign(*this, other); return *this; }
|
||||
|
||||
QCborValue::Type type() const { return concreteType(); }
|
||||
bool isInteger() const { return type() == QCborValue::Integer; }
|
||||
|
|
@ -426,6 +432,9 @@ private:
|
|||
friend class QCborValueRefPtr;
|
||||
|
||||
// static so we can pass this by value
|
||||
static void assign(QCborValueRef that, const QCborValue &other);
|
||||
static void assign(QCborValueRef that, QCborValue &&other);
|
||||
static void assign(QCborValueRef that, const QCborValueRef other);
|
||||
static QCborValue concrete(QCborValueRef that) Q_DECL_NOTHROW;
|
||||
QCborValue concrete() const Q_DECL_NOTHROW { return concrete(*this); }
|
||||
|
||||
|
|
|
|||
|
|
@ -187,18 +187,18 @@ public:
|
|||
return e.container;
|
||||
}
|
||||
|
||||
void replaceAt_complex(QtCbor::Element &e, const QCborValue &value);
|
||||
void replaceAt_internal(QtCbor::Element &e, const QCborValue &value)
|
||||
void replaceAt_complex(QtCbor::Element &e, const QCborValue &value, ContainerDisposition disp);
|
||||
void replaceAt_internal(QtCbor::Element &e, const QCborValue &value, ContainerDisposition disp)
|
||||
{
|
||||
if (value.container)
|
||||
return replaceAt_complex(e, value);
|
||||
return replaceAt_complex(e, value, disp);
|
||||
|
||||
e.value = value.value_helper();
|
||||
e.type = value.type();
|
||||
if (value.isContainer())
|
||||
e.container = nullptr;
|
||||
}
|
||||
void replaceAt(qsizetype idx, const QCborValue &value)
|
||||
void replaceAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
|
||||
{
|
||||
QtCbor::Element &e = elements[idx];
|
||||
if (e.flags & QtCbor::Element::IsContainer) {
|
||||
|
|
@ -208,11 +208,11 @@ public:
|
|||
} else if (e.flags & QtCbor::Element::HasByteData) {
|
||||
usedData -= byteData(idx)->len + sizeof(QtCbor::ByteData);
|
||||
}
|
||||
replaceAt_internal(e, value);
|
||||
replaceAt_internal(e, value, disp);
|
||||
}
|
||||
void insertAt(qsizetype idx, const QCborValue &value)
|
||||
void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
|
||||
{
|
||||
replaceAt_internal(*elements.insert(elements.begin() + idx, {}), value);
|
||||
replaceAt_internal(*elements.insert(elements.begin() + idx, {}), value, disp);
|
||||
}
|
||||
|
||||
void append(QtCbor::Undefined)
|
||||
|
|
@ -277,6 +277,11 @@ public:
|
|||
return data->toUtf8String();
|
||||
}
|
||||
|
||||
static void resetValue(QCborValue &v)
|
||||
{
|
||||
v.container = nullptr;
|
||||
}
|
||||
|
||||
static QCborValue makeValue(QCborValue::Type type, qint64 n, QCborContainerPrivate *d = nullptr,
|
||||
ContainerDisposition disp = CopyContainer)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue