QBitArray: fix fromBits() and actually test it
When I initially added it, it was ony for QCborValue, but I never added the tests. Turns out there were two bugs: [ChangeLog][QtCore][QBitArray] Fixed two bugs that caused QBitArrays created using fromBits() not to compare equal to the equivalent QBitArray created using other methods if the size was zero or not a multiple of 4. If the size modulus 8 was 5, 6, or 7, the data was actually incorrect. Fixes: QTBUG-77285 Change-Id: Ife213d861bb14c1787e1fffd15b70573d162042c Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
39e937a538
commit
6ce9404a6e
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Intel Corporation.
|
||||
** Copyright (C) 2019 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -132,12 +132,12 @@ QT_BEGIN_NAMESPACE
|
||||
* We overallocate the byte array by 1 byte. The first user bit is at
|
||||
* d.data()[1]. On the extra first byte, we store the difference between the
|
||||
* number of bits in the byte array (including this byte) and the number of
|
||||
* bits in the bit array. Therefore, it's always a number between 8 and 15.
|
||||
* bits in the bit array. Therefore, for a non-empty QBitArray, it's always a
|
||||
* number between 8 and 15. For the empty one, d is the an empty QByteArray and
|
||||
* *d.constData() is the QByteArray's terminating NUL (0) byte.
|
||||
*
|
||||
* This allows for fast calculation of the bit array size:
|
||||
* inline int size() const { return (d.size() << 3) - *d.constData(); }
|
||||
*
|
||||
* Note: for an array of zero size, *d.constData() is the QByteArray implicit NUL.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -326,6 +326,8 @@ void QBitArray::fill(bool value, int begin, int end)
|
||||
QBitArray QBitArray::fromBits(const char *data, qsizetype size)
|
||||
{
|
||||
QBitArray result;
|
||||
if (size == 0)
|
||||
return result;
|
||||
qsizetype nbytes = (size + 7) / 8;
|
||||
|
||||
result.d = QByteArray(nbytes + 1, Qt::Uninitialized);
|
||||
@ -334,7 +336,7 @@ QBitArray QBitArray::fromBits(const char *data, qsizetype size)
|
||||
|
||||
// clear any unused bits from the last byte
|
||||
if (size & 7)
|
||||
bits[nbytes] &= 0xffU >> (size & 7);
|
||||
bits[nbytes] &= 0xffU >> (8 - (size & 7));
|
||||
|
||||
*bits = result.d.size() * 8 - size;
|
||||
return result;
|
||||
|
@ -84,6 +84,8 @@ private slots:
|
||||
void operator_noteq();
|
||||
|
||||
void resize();
|
||||
void fromBits_data();
|
||||
void fromBits();
|
||||
};
|
||||
|
||||
void tst_QBitArray::size_data()
|
||||
@ -610,5 +612,60 @@ void tst_QBitArray::resize()
|
||||
|
||||
}
|
||||
|
||||
void tst_QBitArray::fromBits_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("data");
|
||||
QTest::addColumn<int>("size");
|
||||
QTest::addColumn<QBitArray>("expected");
|
||||
|
||||
QTest::newRow("empty") << QByteArray() << 0 << QBitArray();
|
||||
|
||||
auto add = [](const QByteArray &tag, const char *data) {
|
||||
QTest::newRow(tag) << QByteArray(data, (tag.size() + 7) / 8) << tag.size()
|
||||
<< QStringToQBitArray(tag);
|
||||
};
|
||||
|
||||
// "0" to "0000000000000000"
|
||||
for (int i = 1; i < 16; ++i) {
|
||||
char zero[2] = { 0, 0 };
|
||||
QByteArray pattern(i, '0');
|
||||
add(pattern, zero);
|
||||
}
|
||||
|
||||
// "1" to "1111111111111111"
|
||||
for (int i = 1; i < 16; ++i) {
|
||||
char one[2] = { '\xff', '\xff' };
|
||||
QByteArray pattern(i, '1');
|
||||
add(pattern, one);
|
||||
}
|
||||
|
||||
// trailing 0 and 1
|
||||
char zero = 1;
|
||||
char one = 0;
|
||||
QByteArray pzero = "1";
|
||||
QByteArray pone = "0";
|
||||
for (int i = 2; i < 8; ++i) {
|
||||
zero <<= 1;
|
||||
pzero.prepend('0');
|
||||
add(pzero, &zero);
|
||||
|
||||
one = (one << 1) | 1;
|
||||
pone.prepend('1');
|
||||
add(pone, &one);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QBitArray::fromBits()
|
||||
{
|
||||
QFETCH(QByteArray, data);
|
||||
QFETCH(int, size);
|
||||
QFETCH(QBitArray, expected);
|
||||
|
||||
QBitArray fromBits = QBitArray::fromBits(data, size);
|
||||
QCOMPARE(fromBits, expected);
|
||||
|
||||
QCOMPARE(QBitArray::fromBits(fromBits.bits(), fromBits.size()), expected);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QBitArray)
|
||||
#include "tst_qbitarray.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user