Fully support operator[] on QCborValue and QCborValueRef
Added operator[] to QCborValueRef and mutating operator[] both there and in QCborValue. If the value (referenced) is not a container, it is replaced with a map and a reference into the result is returned. If the value is an array and the key is a string, negative, or more than 0xffff, the array is first converted to a map. Change-Id: Ibbc9e480fb25eb3d05547c8a1b99e762b2a68b68 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
f09fc1f352
commit
779a73762d
@ -272,6 +272,7 @@ private:
|
||||
void detach(qsizetype reserve = 0);
|
||||
|
||||
friend QCborValue;
|
||||
friend QCborValueRef;
|
||||
explicit QCborArray(QCborContainerPrivate &dd) noexcept;
|
||||
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
|
||||
};
|
||||
|
@ -118,6 +118,8 @@ public:
|
||||
QCborValueRef item; // points to the value
|
||||
friend class Iterator;
|
||||
friend class QCborMap;
|
||||
friend class QCborValue;
|
||||
friend class QCborValueRef;
|
||||
ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
|
||||
public:
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
@ -323,9 +325,10 @@ public:
|
||||
QJsonObject toJsonObject() const;
|
||||
|
||||
private:
|
||||
friend class QCborValue;
|
||||
friend class QCborValueRef;
|
||||
void detach(qsizetype reserve = 0);
|
||||
|
||||
friend QCborValue;
|
||||
explicit QCborMap(QCborContainerPrivate &dd) noexcept;
|
||||
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
|
||||
};
|
||||
|
@ -128,10 +128,11 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
Such values are completely valid and may appear in CBOR streams, unlike
|
||||
JSON content and QJsonValue's undefined bit. But like QJsonValue's
|
||||
Undefined, it is returned by QCborArray::value() when out of range or
|
||||
QCborMap::operator[] when the key is not found in the container. It is not
|
||||
possible to tell such a case apart from the value of Undefined, so if that
|
||||
is required, check the QCborArray size and use the QCborMap iterator API.
|
||||
Undefined, it is returned by a CBOR container's value() or read-only
|
||||
operator[] for invalid look-ups (index out of range for QCborArray, or key
|
||||
not found for QCborMap). It is not possible to tell such a case apart from
|
||||
the value of Undefined, so if that is required, check the QCborArray size
|
||||
and use the QCborMap iterator API.
|
||||
|
||||
\section1 Simple types
|
||||
|
||||
@ -457,7 +458,7 @@ QT_BEGIN_NAMESPACE
|
||||
\fn QCborValue::QCborValue(QCborValue &&other)
|
||||
\overload
|
||||
|
||||
Moves the contents of the \a other CBorValue object into this one and frees
|
||||
Moves the contents of the \a other QCborValue object into this one and frees
|
||||
the resources of this one.
|
||||
*/
|
||||
|
||||
@ -465,7 +466,7 @@ QT_BEGIN_NAMESPACE
|
||||
\fn QCborValue &&QCborValue::operator=(QCborValue &&other)
|
||||
\overload
|
||||
|
||||
Moves the contents of the \a other CBorValue object into this one and frees
|
||||
Moves the contents of the \a other QCborValue object into this one and frees
|
||||
the resources of this one. Returns a reference to this object.
|
||||
*/
|
||||
|
||||
@ -2107,15 +2108,16 @@ const QCborValue QCborValue::operator[](QLatin1String key) const
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
If this QCborValue is a QCborMap, searches elements for the value whose key
|
||||
matches \a key. If this is an array, returns the element whose index is \a
|
||||
key. If there's no matching value in the array or map, or if this
|
||||
matches \a key. If this is a QCborArray, returns the element whose index is
|
||||
\a key. If there's no matching value in the array or map, or if this
|
||||
QCborValue object is not an array or map, returns the undefined value.
|
||||
|
||||
\sa operator[], QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find(), QCborArray::operator[], QCborArray::at()
|
||||
*/
|
||||
|
||||
const QCborValue QCborValue::operator[](qint64 key) const
|
||||
{
|
||||
if (isMap())
|
||||
@ -2125,6 +2127,191 @@ const QCborValue QCborValue::operator[](qint64 key) const
|
||||
return QCborValue();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array)
|
||||
{
|
||||
if (array.size())
|
||||
qWarning("Using CBOR array as map forced conversion");
|
||||
QCborMap map;
|
||||
for (qsizetype i = array.size(); i-- > 0; ) {
|
||||
QCborValue entry = array.at(i);
|
||||
// Ignore padding entries that may have been added to grow the array
|
||||
// when inserting past its end:
|
||||
if (!entry.isInvalid())
|
||||
map[i] = entry;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size)
|
||||
{
|
||||
auto replace = QCborContainerPrivate::detach(container, size);
|
||||
Q_ASSERT(replace);
|
||||
if (replace != container) {
|
||||
if (container)
|
||||
container->deref();
|
||||
replace->ref.ref();
|
||||
}
|
||||
return replace;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizetype index)
|
||||
{
|
||||
auto replace = QCborContainerPrivate::grow(container, index);
|
||||
Q_ASSERT(replace);
|
||||
if (replace != container) {
|
||||
if (container)
|
||||
container->deref();
|
||||
replace->ref.ref();
|
||||
}
|
||||
if (replace->elements.size() == index)
|
||||
replace->append(Undefined());
|
||||
else
|
||||
Q_ASSERT(replace->elements.size() > index);
|
||||
return replace;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a QCborValueRef that can be used to read or modify the entry in
|
||||
this, as a map, with the given \a key. When this QCborValue is a QCborMap,
|
||||
this function is equivalent to the matching operator[] on that map.
|
||||
|
||||
Before returning the reference: if this QCborValue was an array, it is first
|
||||
converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
|
||||
with valid \c{array[i]}); otherwise, if it was not a map it will be
|
||||
over-written with an empty map.
|
||||
|
||||
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find()
|
||||
*/
|
||||
QCborValueRef QCborValue::operator[](const QString &key)
|
||||
{
|
||||
if (!isMap())
|
||||
*this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
|
||||
|
||||
const qsizetype size = container ? container->elements.size() : 0;
|
||||
qsizetype index = size + 1;
|
||||
bool found = false;
|
||||
if (container) {
|
||||
QCborMap proxy(*container);
|
||||
auto it = proxy.constFind(key);
|
||||
if (it < proxy.constEnd()) {
|
||||
found = true;
|
||||
index = it.item.i;
|
||||
}
|
||||
}
|
||||
|
||||
container = maybeDetach(container, size + (found ? 0 : 2));
|
||||
Q_ASSERT(container);
|
||||
if (!found) {
|
||||
container->append(key);
|
||||
container->append(QCborValue());
|
||||
}
|
||||
Q_ASSERT(index & 1 && !(container->elements.size() & 1));
|
||||
Q_ASSERT(index < container->elements.size());
|
||||
return { container, index };
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
Returns a QCborValueRef that can be used to read or modify the entry in
|
||||
this, as a map, with the given \a key. When this QCborValue is a QCborMap,
|
||||
this function is equivalent to the matching operator[] on that map.
|
||||
|
||||
Before returning the reference: if this QCborValue was an array, it is first
|
||||
converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
|
||||
with valid \c{array[i]}); otherwise, if it was not a map it will be
|
||||
over-written with an empty map.
|
||||
|
||||
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find()
|
||||
*/
|
||||
QCborValueRef QCborValue::operator[](QLatin1String key)
|
||||
{
|
||||
if (!isMap())
|
||||
*this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
|
||||
|
||||
const qsizetype size = container ? container->elements.size() : 0;
|
||||
qsizetype index = size + 1;
|
||||
bool found = false;
|
||||
if (container) {
|
||||
QCborMap proxy(*container);
|
||||
auto it = proxy.constFind(key);
|
||||
if (it < proxy.constEnd()) {
|
||||
found = true;
|
||||
index = it.item.i;
|
||||
}
|
||||
}
|
||||
|
||||
container = maybeDetach(container, size + (found ? 0 : 2));
|
||||
Q_ASSERT(container);
|
||||
if (!found) {
|
||||
container->append(key);
|
||||
container->append(QCborValue());
|
||||
}
|
||||
Q_ASSERT(index & 1 && !(container->elements.size() & 1));
|
||||
Q_ASSERT(index < container->elements.size());
|
||||
return { container, index };
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
Returns a QCborValueRef that can be used to read or modify the entry in
|
||||
this, as a map or array, with the given \a key. When this QCborValue is a
|
||||
QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
|
||||
equivalent to the matching operator[] on that map or array.
|
||||
|
||||
Before returning the reference: if this QCborValue was an array but the key
|
||||
is out of range, the array is first converted to a map (so that \c{map[i]}
|
||||
is \c{array[i]} for each index, \c i, with valid \c{array[i]}); otherwise,
|
||||
if it was not a map it will be over-written with an empty map.
|
||||
|
||||
\sa operator[], QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find(), QCborArray::operator[], QCborArray::at()
|
||||
*/
|
||||
QCborValueRef QCborValue::operator[](qint64 key)
|
||||
{
|
||||
if (isArray() && key >= 0 && key < 0x10000) {
|
||||
container = maybeGrow(container, key);
|
||||
return { container, qsizetype(key) };
|
||||
}
|
||||
if (!isMap())
|
||||
*this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
|
||||
|
||||
const qsizetype size = container ? container->elements.size() : 0;
|
||||
Q_ASSERT(!(size & 1));
|
||||
qsizetype index = size + 1;
|
||||
bool found = false;
|
||||
if (container) {
|
||||
QCborMap proxy(*container);
|
||||
auto it = proxy.constFind(key);
|
||||
if (it < proxy.constEnd()) {
|
||||
found = true;
|
||||
index = it.item.i;
|
||||
}
|
||||
}
|
||||
|
||||
container = maybeDetach(container, size + (found ? 0 : 2));
|
||||
Q_ASSERT(container);
|
||||
if (!found) {
|
||||
container->append(key);
|
||||
container->append(QCborValue());
|
||||
}
|
||||
Q_ASSERT(index & 1 && !(container->elements.size() & 1));
|
||||
Q_ASSERT(index < container->elements.size());
|
||||
return { container, index };
|
||||
}
|
||||
|
||||
/*!
|
||||
Decodes one item from the CBOR stream found in \a reader and returns the
|
||||
equivalent representation. This function is recursive: if the item is a map
|
||||
@ -2389,6 +2576,255 @@ QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept
|
||||
return self.d->elements.at(self.i).type;
|
||||
}
|
||||
|
||||
/*!
|
||||
If this QCborValueRef refers to a QCborMap, searches elements for the value
|
||||
whose key matches \a key. If there's no key matching \a key in the map or if
|
||||
this QCborValueRef object is not a map, returns the undefined value.
|
||||
|
||||
This function is equivalent to:
|
||||
|
||||
\code
|
||||
value.toMap().value(key);
|
||||
\endcode
|
||||
|
||||
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find()
|
||||
*/
|
||||
const QCborValue QCborValueRef::operator[](const QString &key) const
|
||||
{
|
||||
const QCborValue item = d->valueAt(i);
|
||||
return item[key];
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
If this QCborValueRef refers to a QCborMap, searches elements for the value
|
||||
whose key matches \a key. If there's no key matching \a key in the map or if
|
||||
this QCborValueRef object is not a map, returns the undefined value.
|
||||
|
||||
This function is equivalent to:
|
||||
|
||||
\code
|
||||
value.toMap().value(key);
|
||||
\endcode
|
||||
|
||||
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find()
|
||||
*/
|
||||
const QCborValue QCborValueRef::operator[](QLatin1String key) const
|
||||
{
|
||||
const QCborValue item = d->valueAt(i);
|
||||
return item[key];
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
If this QCborValueRef refers to a QCborMap, searches elements for the value
|
||||
whose key matches \a key. If this is a QCborArray, returns the element whose
|
||||
index is \a key. If there's no matching value in the array or map, or if
|
||||
this QCborValueRef object is not an array or map, returns the undefined
|
||||
value.
|
||||
|
||||
\sa operator[], QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find(), QCborArray::operator[], QCborArray::at()
|
||||
*/
|
||||
const QCborValue QCborValueRef::operator[](qint64 key) const
|
||||
{
|
||||
const QCborValue item = d->valueAt(i);
|
||||
return item[key];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a QCborValueRef that can be used to read or modify the entry in
|
||||
this, as a map, with the given \a key. When this QCborValueRef refers to a
|
||||
QCborMap, this function is equivalent to the matching operator[] on that
|
||||
map.
|
||||
|
||||
Before returning the reference: if the QCborValue referenced was an array,
|
||||
it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
|
||||
index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
|
||||
will be over-written with an empty map.
|
||||
|
||||
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find()
|
||||
*/
|
||||
QCborValueRef QCborValueRef::operator[](const QString &key)
|
||||
{
|
||||
auto &e = d->elements[i];
|
||||
qsizetype size = 0;
|
||||
if (e.flags & QtCbor::Element::IsContainer) {
|
||||
if (e.container) {
|
||||
if (e.type == QCborValue::Array) {
|
||||
QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
|
||||
qSwap(e.container, repack.container);
|
||||
} else if (e.type != QCborValue::Map) {
|
||||
e.container->deref();
|
||||
e.container = nullptr;
|
||||
}
|
||||
}
|
||||
e.type = QCborValue::Map;
|
||||
if (e.container)
|
||||
size = e.container->elements.size();
|
||||
} else {
|
||||
// Stomp any prior e.value, replace with a map (that we'll grow)
|
||||
e.container = nullptr;
|
||||
e.type = QCborValue::Map;
|
||||
e.flags = QtCbor::Element::IsContainer;
|
||||
}
|
||||
|
||||
qsizetype index = size + 1;
|
||||
bool found = false;
|
||||
if (e.container) {
|
||||
QCborMap proxy(*e.container);
|
||||
auto it = proxy.constFind(key);
|
||||
if (it < proxy.constEnd()) {
|
||||
found = true;
|
||||
index = it.item.i;
|
||||
}
|
||||
}
|
||||
|
||||
e.container = maybeDetach(e.container, size + (found ? 0 : 2));
|
||||
Q_ASSERT(e.container);
|
||||
if (!found) {
|
||||
e.container->append(key);
|
||||
e.container->append(QCborValue());
|
||||
}
|
||||
Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
|
||||
Q_ASSERT(index < e.container->elements.size());
|
||||
return { e.container, index };
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
Returns a QCborValueRef that can be used to read or modify the entry in
|
||||
this, as a map, with the given \a key. When this QCborValue is a QCborMap,
|
||||
this function is equivalent to the matching operator[] on that map.
|
||||
|
||||
Before returning the reference: if the QCborValue referenced was an array,
|
||||
it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
|
||||
index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
|
||||
will be over-written with an empty map.
|
||||
|
||||
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find()
|
||||
*/
|
||||
QCborValueRef QCborValueRef::operator[](QLatin1String key)
|
||||
{
|
||||
auto &e = d->elements[i];
|
||||
qsizetype size = 0;
|
||||
if (e.flags & QtCbor::Element::IsContainer) {
|
||||
if (e.container) {
|
||||
if (e.type == QCborValue::Array) {
|
||||
QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
|
||||
qSwap(e.container, repack.container);
|
||||
} else if (e.type != QCborValue::Map) {
|
||||
e.container->deref();
|
||||
e.container = nullptr;
|
||||
}
|
||||
}
|
||||
e.type = QCborValue::Map;
|
||||
if (e.container)
|
||||
size = e.container->elements.size();
|
||||
} else {
|
||||
// Stomp any prior e.value, replace with a map (that we'll grow)
|
||||
e.container = nullptr;
|
||||
e.type = QCborValue::Map;
|
||||
e.flags = QtCbor::Element::IsContainer;
|
||||
}
|
||||
|
||||
qsizetype index = size + 1;
|
||||
bool found = false;
|
||||
if (e.container) {
|
||||
QCborMap proxy(*e.container);
|
||||
auto it = proxy.constFind(key);
|
||||
if (it < proxy.constEnd()) {
|
||||
found = true;
|
||||
index = it.item.i;
|
||||
}
|
||||
}
|
||||
|
||||
e.container = maybeDetach(e.container, size + (found ? 0 : 2));
|
||||
Q_ASSERT(e.container);
|
||||
if (!found) {
|
||||
e.container->append(key);
|
||||
e.container->append(QCborValue());
|
||||
}
|
||||
Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
|
||||
Q_ASSERT(index < e.container->elements.size());
|
||||
return { e.container, index };
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
Returns a QCborValueRef that can be used to read or modify the entry in
|
||||
this, as a map or array, with the given \a key. When this QCborValue is a
|
||||
QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
|
||||
equivalent to the matching operator[] on that map or array.
|
||||
|
||||
Before returning the reference: if the QCborValue referenced was an array
|
||||
but the key is out of range, the array is first converted to a map (so that
|
||||
\c{map[i]} is \c{array[i]} for each index, \c i, with valid \c{array[i]});
|
||||
otherwise, if it was not a map it will be over-written with an empty map.
|
||||
|
||||
\sa operator[], QCborMap::operator[], QCborMap::value(),
|
||||
QCborMap::find(), QCborArray::operator[], QCborArray::at()
|
||||
*/
|
||||
QCborValueRef QCborValueRef::operator[](qint64 key)
|
||||
{
|
||||
auto &e = d->elements[i];
|
||||
if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) {
|
||||
e.container = maybeGrow(e.container, key);
|
||||
return { e.container, qsizetype(key) };
|
||||
}
|
||||
qsizetype size = 0;
|
||||
if (e.flags & QtCbor::Element::IsContainer) {
|
||||
if (e.container) {
|
||||
if (e.type == QCborValue::Array) {
|
||||
QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
|
||||
qSwap(e.container, repack.container);
|
||||
} else if (e.type != QCborValue::Map) {
|
||||
e.container->deref();
|
||||
e.container = nullptr;
|
||||
}
|
||||
}
|
||||
e.type = QCborValue::Map;
|
||||
if (e.container)
|
||||
size = e.container->elements.size();
|
||||
} else {
|
||||
// Stomp any prior e.value, replace with a map (that we'll grow)
|
||||
e.container = nullptr;
|
||||
e.type = QCborValue::Map;
|
||||
e.flags = QtCbor::Element::IsContainer;
|
||||
}
|
||||
Q_ASSERT(!(size & 1));
|
||||
|
||||
qsizetype index = size + 1;
|
||||
bool found = false;
|
||||
if (e.container) {
|
||||
QCborMap proxy(*e.container);
|
||||
auto it = proxy.constFind(key);
|
||||
if (it < proxy.constEnd()) {
|
||||
found = true;
|
||||
index = it.item.i;
|
||||
}
|
||||
}
|
||||
|
||||
e.container = maybeDetach(e.container, size + (found ? 0 : 2));
|
||||
Q_ASSERT(e.container);
|
||||
if (!found) {
|
||||
e.container->append(key);
|
||||
e.container->append(QCborValue());
|
||||
}
|
||||
Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
|
||||
Q_ASSERT(index < e.container->elements.size());
|
||||
return { e.container, index };
|
||||
}
|
||||
|
||||
|
||||
inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept
|
||||
: d(&dd)
|
||||
{
|
||||
|
@ -77,6 +77,7 @@ struct QCborParserError
|
||||
QString errorString() const { return error.toString(); }
|
||||
};
|
||||
|
||||
class QCborValueRef;
|
||||
class QCborContainerPrivate;
|
||||
class Q_CORE_EXPORT QCborValue
|
||||
{
|
||||
@ -246,6 +247,9 @@ public:
|
||||
const QCborValue operator[](const QString &key) const;
|
||||
const QCborValue operator[](QLatin1String key) const;
|
||||
const QCborValue operator[](qint64 key) const;
|
||||
QCborValueRef operator[](qint64 key);
|
||||
QCborValueRef operator[](QLatin1String key);
|
||||
QCborValueRef operator[](const QString & key);
|
||||
|
||||
int compare(const QCborValue &other) const;
|
||||
#if 0 && QT_HAS_INCLUDE(<compare>)
|
||||
@ -387,6 +391,13 @@ public:
|
||||
QCborMap toMap() const;
|
||||
QCborMap toMap(const QCborMap &m) const;
|
||||
|
||||
const QCborValue operator[](const QString &key) const;
|
||||
const QCborValue operator[](QLatin1String key) const;
|
||||
const QCborValue operator[](qint64 key) const;
|
||||
QCborValueRef operator[](qint64 key);
|
||||
QCborValueRef operator[](QLatin1String key);
|
||||
QCborValueRef operator[](const QString & key);
|
||||
|
||||
int compare(const QCborValue &other) const
|
||||
{ return concrete().compare(other); }
|
||||
#if 0 && QT_HAS_INCLUDE(<compare>)
|
||||
@ -417,6 +428,7 @@ public:
|
||||
{ return concrete().toDiagnosticNotation(opt); }
|
||||
|
||||
private:
|
||||
friend class QCborValue;
|
||||
friend class QCborArray;
|
||||
friend class QCborMap;
|
||||
friend class QCborContainerPrivate;
|
||||
|
@ -384,11 +384,17 @@ void tst_QCborValue::arrayDefaultInitialization()
|
||||
QVERIFY(v.isArray());
|
||||
QVERIFY(!v.isMap());
|
||||
QVERIFY(!v.isTag());
|
||||
QVERIFY(v[0].isUndefined());
|
||||
|
||||
QCborArray a2 = v.toArray();
|
||||
QVERIFY(a2.isEmpty());
|
||||
QCOMPARE(a2, a);
|
||||
auto front = v[0];
|
||||
QVERIFY(front.isUndefined());
|
||||
front = 1;
|
||||
QCOMPARE(v[0], 1);
|
||||
QVERIFY(a2.isEmpty());
|
||||
a2 = v.toArray();
|
||||
QCOMPARE(a2.size(), 1);
|
||||
}
|
||||
|
||||
void tst_QCborValue::mapDefaultInitialization()
|
||||
@ -425,7 +431,7 @@ void tst_QCborValue::mapDefaultInitialization()
|
||||
QVERIFY(m == QCborMap{});
|
||||
QVERIFY(QCborMap{} == m);
|
||||
|
||||
QCborValue v(m);
|
||||
const QCborValue v(m);
|
||||
QVERIFY(v.isMap());
|
||||
QVERIFY(!v.isArray());
|
||||
QVERIFY(!v.isTag());
|
||||
@ -727,6 +733,31 @@ void tst_QCborValue::arrayMutation()
|
||||
QCOMPARE(a.at(1), QCborValue(-1));
|
||||
QCOMPARE(a2.at(1), QCborValue(nullptr));
|
||||
QCOMPARE(++it, end);
|
||||
|
||||
// Array accessed via value:
|
||||
QCborValue val(a);
|
||||
val[2] = QCborArray{2, 3, 5, 7};
|
||||
QCOMPARE(a.size(), 2); // Unchanged
|
||||
QVERIFY(val.isArray());
|
||||
QCOMPARE(val.toArray().size(), 3);
|
||||
val[2][4] = 17;
|
||||
QVERIFY(val.isArray());
|
||||
QVERIFY(val[2].isArray());
|
||||
QCOMPARE(val[2].toArray().size(), 5);
|
||||
QCOMPARE(val[2][4], 17);
|
||||
QCOMPARE(val.toArray().size(), 3);
|
||||
val[3] = 42;
|
||||
QVERIFY(val.isArray());
|
||||
QCOMPARE(val.toArray().size(), 4);
|
||||
QCOMPARE(val[3], 42);
|
||||
|
||||
// Coerce to map on string key:
|
||||
const QLatin1String any("any");
|
||||
val[any] = any;
|
||||
QVERIFY(val.isMap());
|
||||
QCOMPARE(val.toMap().size(), 5);
|
||||
QVERIFY(val[2].isArray());
|
||||
QCOMPARE(val[2].toArray().size(), 5);
|
||||
}
|
||||
|
||||
void tst_QCborValue::mapMutation()
|
||||
@ -782,6 +813,30 @@ void tst_QCborValue::mapMutation()
|
||||
QCOMPARE((m.end() - 1)->toInteger(), -1);
|
||||
QVERIFY((m2.end() - 1)->isNull());
|
||||
QCOMPARE(++it, end);
|
||||
|
||||
// Map accessed via value:
|
||||
QCborValue val(m);
|
||||
val[7] = QCborMap({{0, 2}, {1, 3}, {2, 5}});
|
||||
QCOMPARE(m.size(), 2); // Unchanged
|
||||
QVERIFY(val.isMap());
|
||||
QCOMPARE(val.toMap().size(), 3);
|
||||
val[7][3] = 11;
|
||||
QVERIFY(val.isMap());
|
||||
QVERIFY(val[7].isMap());
|
||||
QCOMPARE(val[7].toMap().size(), 4);
|
||||
val[14] = 42;
|
||||
QVERIFY(val.isMap());
|
||||
QCOMPARE(val.toMap().size(), 4);
|
||||
|
||||
const QLatin1String any("any");
|
||||
const QString hello(QStringLiteral("Hello World"));
|
||||
val[any][3][hello] = any;
|
||||
QVERIFY(val.isMap());
|
||||
QCOMPARE(val.toMap().size(), 5);
|
||||
QVERIFY(val[any].isMap());
|
||||
QCOMPARE(val[any].toMap().size(), 1);
|
||||
QVERIFY(val[any][3].isMap());
|
||||
QCOMPARE(val[any][3].toMap().size(), 1);
|
||||
}
|
||||
|
||||
void tst_QCborValue::arrayPrepend()
|
||||
|
Loading…
Reference in New Issue
Block a user