summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2019-08-01 22:56:30 -0700
committerThiago Macieira <thiago.macieira@intel.com>2019-08-08 20:27:04 -0700
commit6ce9404a6e7ad6ba3ff37f6890fe400c643c3d52 (patch)
tree3fe43c54f408a69627630008176b3fbd9e4edc22
parent39e937a538325c4fc40a790496f2a39d28f8eba4 (diff)
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>
-rw-r--r--src/corelib/tools/qbitarray.cpp12
-rw-r--r--tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp57
2 files changed, 64 insertions, 5 deletions
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index 4e8e3c241e..94aadf7fdf 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -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;
diff --git a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp
index d19eac7530..9a7c099228 100644
--- a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp
+++ b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp
@@ -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"