Change QCborArray to pad with invalid on inserting past end

Likewise have mutating operator[] insert an invalid entry at its
target index, if beyond the end of the array. This makes it possible
to fill an array from high index to low, for example.

Change-Id: If71699c20e2623142214ce2c11c4d6e4a120c989
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2018-09-20 13:36:05 +02:00
parent 7f079bf9d0
commit ff7f09d187
4 changed files with 41 additions and 10 deletions

View File

@ -297,7 +297,8 @@ QCborValue QCborArray::at(qsizetype i) const
\fn QCborValueRef QCborArray::operator[](qsizetype i)
Returns a reference to the QCborValue element at position \a i in the
array. The array must have at least \a i elements.
array. Indices beyond the end of the array will grow the array, filling
with undefined entries, until it has an entry at the specified index.
QCborValueRef has the exact same API as \l QCborValue, with one important
difference: if you assign new values to it, this map will be updated with
@ -311,27 +312,34 @@ 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.
Inserts \a value into the array at position \a i in this array. If \a i is
-1, the entry is appended to the array. Pads the array with invalid entries
if \a i is greater than the prior size of the array.
\sa at(), operator[](), first(), last(), prepend(), append(),
removeAt(), takeAt(), extract()
*/
void QCborArray::insert(qsizetype i, const QCborValue &value)
{
Q_ASSERT(size_t(i) <= size_t(size()) || i == -1);
if (i < 0)
if (i < 0) {
Q_ASSERT(i == -1);
i = size();
detach(qMax(i + 1, size()));
detach(i + 1);
} else {
d = QCborContainerPrivate::grow(d.data(), i); // detaches
}
d->insertAt(i, value);
}
void QCborArray::insert(qsizetype i, QCborValue &&value)
{
Q_ASSERT(size_t(i) <= size_t(size()) || i == -1);
if (i < 0)
if (i < 0) {
Q_ASSERT(i == -1);
i = size();
detach(qMax(i + 1, size()));
detach(i + 1);
} else {
d = QCborContainerPrivate::grow(d.data(), i); // detaches
}
d->insertAt(i, value, QCborContainerPrivate::MoveContainer);
QCborContainerPrivate::resetValue(value);
}

View File

@ -188,7 +188,12 @@ public:
QCborValue operator[](qsizetype i) const { return at(i); }
QCborValueRef first() { Q_ASSERT(!isEmpty()); return begin()[0]; }
QCborValueRef last() { Q_ASSERT(!isEmpty()); return begin()[size() - 1]; }
QCborValueRef operator[](qsizetype i) { Q_ASSERT(i < size()); return begin()[i]; }
QCborValueRef operator[](qsizetype i)
{
if (i >= size())
insert(i, QCborValue());
return begin()[i];
}
void insert(qsizetype i, const QCborValue &value);
void insert(qsizetype i, QCborValue &&value);

View File

@ -859,6 +859,23 @@ QCborContainerPrivate *QCborContainerPrivate::detach(QCborContainerPrivate *d, q
return d;
}
/*!
Prepare for an insertion at position \a index
Detaches and ensures there are at least index entries in the array, padding
with Undefined as needed.
*/
QCborContainerPrivate *QCborContainerPrivate::grow(QCborContainerPrivate *d, qsizetype index)
{
Q_ASSERT(index >= 0);
d = detach(d, index + 1);
Q_ASSERT(d);
int j = d->elements.size();
while (j < index)
d->append(Undefined());
return d;
}
// 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,

View File

@ -136,6 +136,7 @@ public:
void compact(qsizetype reserved);
static QCborContainerPrivate *clone(QCborContainerPrivate *d, qsizetype reserved = -1);
static QCborContainerPrivate *detach(QCborContainerPrivate *d, qsizetype reserved);
static QCborContainerPrivate *grow(QCborContainerPrivate *d, qsizetype index);
qptrdiff addByteData(const char *block, qsizetype len)
{