Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qbitarray.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2019 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qbitarray.h"
6#include <qalgorithms.h>
7#include <qdatastream.h>
8#include <qdebug.h>
9#include <qendian.h>
10#include <string.h>
11
13
93/*
94 * QBitArray construction note:
95 *
96 * We overallocate the byte array by 1 byte. The first user bit is at
97 * d.data()[1]. On the extra first byte, we store the difference between the
98 * number of bits in the byte array (including this byte) and the number of
99 * bits in the bit array. Therefore, for a non-empty QBitArray, it's always a
100 * number between 8 and 15. For the empty one, d is the an empty QByteArray and
101 * *d.constData() is the QByteArray's terminating NUL (0) byte.
102 *
103 * This allows for fast calculation of the bit array size:
104 * inline qsizetype size() const { return (d.size() << 3) - *d.constData(); }
105 */
106
112 : d(size <= 0 ? 0 : 1 + (size + 7) / 8, Qt::Uninitialized)
113{
114 Q_ASSERT_X(size >= 0, "QBitArray::QBitArray", "Size must be greater than or equal to 0.");
115 if (size <= 0)
116 return;
117
118 uchar *c = reinterpret_cast<uchar *>(d.data());
119 memset(c + 1, value ? 0xff : 0, d.size() - 1);
120 *c = d.size() * 8 - size;
121 if (value && size && size & 7)
122 *(c + 1 + size / 8) &= (1 << (size & 7)) - 1;
123}
124
143{
144 qsizetype numBits = 0;
145 const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
146
147 // the loops below will try to read from *end
148 // it's the QByteArray implicit NUL, so it will not change the bit count
149 const quint8 *const end = reinterpret_cast<const quint8 *>(d.end());
150
151 while (bits + 7 <= end) {
152 quint64 v = qFromUnaligned<quint64>(bits);
153 bits += 8;
154 numBits += qsizetype(qPopulationCount(v));
155 }
156 if (bits + 3 <= end) {
157 quint32 v = qFromUnaligned<quint32>(bits);
158 bits += 4;
159 numBits += qsizetype(qPopulationCount(v));
160 }
161 if (bits + 1 < end) {
162 quint16 v = qFromUnaligned<quint16>(bits);
163 bits += 2;
164 numBits += qsizetype(qPopulationCount(v));
165 }
166 if (bits < end)
167 numBits += qsizetype(qPopulationCount(bits[0]));
168
169 return on ? numBits : size() - numBits;
170}
171
185{
186 if (!size) {
187 d.resize(0);
188 } else {
189 qsizetype s = d.size();
190 d.resize(1 + (size + 7) / 8);
191 uchar *c = reinterpret_cast<uchar *>(d.data());
192 if (size > (s << 3))
193 memset(c + s, 0, d.size() - s);
194 else if (size & 7)
195 *(c + 1 + size / 8) &= (1 << (size & 7)) - 1;
196 *c = d.size() * 8 - size;
197 }
198}
199
253{
254 while (begin < end && begin & 0x7)
255 setBit(begin++, value);
257 if (len <= 0)
258 return;
259 qsizetype s = len & ~qsizetype(0x7);
260 uchar *c = reinterpret_cast<uchar *>(d.data());
261 memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
262 begin += s;
263 while (begin < end)
264 setBit(begin++, value);
265}
266
291{
293 if (size == 0)
294 return result;
295 qsizetype nbytes = (size + 7) / 8;
296
297 result.d = QByteArray(nbytes + 1, Qt::Uninitialized);
298 char *bits = result.d.data();
299 memcpy(bits + 1, data, nbytes);
300
301 // clear any unused bits from the last byte
302 if (size & 7)
303 bits[nbytes] &= 0xffU >> (8 - (size & 7));
304
305 *bits = result.d.size() * 8 - size;
306 return result;
307}
308
318quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcept
319{
320 const qsizetype _size = size();
321 if (_size > 32) {
322 if (ok)
323 *ok = false;
324 return 0;
325 }
326
327 if (ok)
328 *ok = true;
329
330 quint32 factor = 1;
331 quint32 total = 0;
332 for (qsizetype i = 0; i < _size; ++i, factor *= 2) {
333 const auto index = endianness == QSysInfo::Endian::LittleEndian ? i : (_size - i - 1);
334 if (testBit(index))
335 total += factor;
336 }
337
338 return total;
339}
340
520{
521 resize(qMax(size(), other.size()));
522 uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
523 const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
524 qsizetype n = other.d.size() - 1;
525 qsizetype p = d.size() - 1 - n;
526 while (n-- > 0)
527 *a1++ &= *a2++;
528 while (p-- > 0)
529 *a1++ = 0;
530 return *this;
531}
532
549{
550 resize(qMax(size(), other.size()));
551 uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
552 const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
553 qsizetype n = other.d.size() - 1;
554 while (n-- > 0)
555 *a1++ |= *a2++;
556 return *this;
557}
558
575{
576 resize(qMax(size(), other.size()));
577 uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
578 const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
579 qsizetype n = other.d.size() - 1;
580 while (n-- > 0)
581 *a1++ ^= *a2++;
582 return *this;
583}
584
596{
597 qsizetype sz = size();
598 QBitArray a(sz);
599 const uchar *a1 = reinterpret_cast<const uchar *>(d.constData()) + 1;
600 uchar *a2 = reinterpret_cast<uchar *>(a.d.data()) + 1;
601 qsizetype n = d.size() - 1;
602
603 while (n-- > 0)
604 *a2++ = ~*a1++;
605
606 if (sz && sz % 8)
607 *(a2 - 1) &= (1 << (sz % 8)) - 1;
608 return a;
609}
610
628{
629 QBitArray tmp = a1;
630 tmp &= a2;
631 return tmp;
632}
633
651{
652 QBitArray tmp = a1;
653 tmp |= a2;
654 return tmp;
655}
656
674{
675 QBitArray tmp = a1;
676 tmp ^= a2;
677 return tmp;
678}
679
721/*****************************************************************************
722 QBitArray stream functions
723 *****************************************************************************/
724
725#ifndef QT_NO_DATASTREAM
735{
736 if (out.version() < QDataStream::Qt_6_0) {
737 quint32 len = ba.size();
738 out << len;
739 if (len > 0)
740 out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
741 return out;
742 } else {
743 quint64 len = ba.size();
744 out << len;
745 if (len > 0)
746 out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
747 return out;
748 }
749}
750
760{
761 ba.clear();
763 if (in.version() < QDataStream::Qt_6_0) {
764 quint32 tmp;
765 in >> tmp;
766 len = tmp;
767 } else {
768 quint64 tmp;
769 in >> tmp;
770 len = tmp;
771 }
772 if (len == 0) {
773 ba.clear();
774 return in;
775 }
776
777 const qsizetype Step = 8 * 1024 * 1024;
778 qsizetype totalBytes = (len + 7) / 8;
779 qsizetype allocated = 0;
780
781 while (allocated < totalBytes) {
782 qsizetype blockSize = qMin(Step, totalBytes - allocated);
783 ba.d.resize(allocated + blockSize + 1);
784 if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
785 ba.clear();
786 in.setStatus(QDataStream::ReadPastEnd);
787 return in;
788 }
789 allocated += blockSize;
790 }
791
792 qsizetype paddingMask = ~((0x1 << (len & 0x7)) - 1);
793 if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) {
794 ba.clear();
796 return in;
797 }
798
799 *ba.d.data() = ba.d.size() * 8 - len;
800 return in;
801}
802#endif // QT_NO_DATASTREAM
803
804#ifndef QT_NO_DEBUG_STREAM
806{
807 QDebugStateSaver saver(dbg);
808 dbg.nospace() << "QBitArray(";
809 for (qsizetype i = 0; i < array.size();) {
810 if (array.testBit(i))
811 dbg << '1';
812 else
813 dbg << '0';
814 i += 1;
815 if (!(i % 4) && (i < array.size()))
816 dbg << ' ';
817 }
818 dbg << ')';
819 return dbg;
820}
821#endif
822
\inmodule QtCore
Definition qbitarray.h:13
QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
Returns a bit array that is the XOR of the bit arrays a1 and a2.
qsizetype count() const
Same as size().
Definition qbitarray.h:32
QBitArray & operator|=(const QBitArray &)
Performs the OR operation between all bits in this bit array and other.
void resize(qsizetype size)
Resizes the bit array to size bits.
void setBit(qsizetype i)
Sets the bit at index position i to 1.
Definition qbitarray.h:88
static QBitArray fromBits(const char *data, qsizetype len)
QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
Returns a bit array that is the OR of the bit arrays a1 and a2.
quint32 toUInt32(QSysInfo::Endian endianness, bool *ok=nullptr) const noexcept
QBitArray & operator&=(const QBitArray &)
Performs the AND operation between all bits in this bit array and other.
bool fill(bool val, qsizetype size=-1)
Sets every bit in the bit array to value, returning true if successful; otherwise returns false.
Definition qbitarray.h:77
QBitArray & operator^=(const QBitArray &)
Performs the XOR operation between all bits in this bit array and other.
QBitArray operator~() const
Returns a bit array that contains the inverted bits of this bit array.
QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
Returns a bit array that is the AND of the bit arrays a1 and a2.
QBitArray() noexcept
Constructs an empty bit array.
Definition qbitarray.h:22
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
iterator end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing just after the last byte in the byte-...
Definition qbytearray.h:432
void clear()
Clears the contents of the byte array and makes it null.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
\inmodule QtCore
Endian
\value BigEndian Big-endian byte order (also called Network byte order) \value LittleEndian Little-en...
Definition qsysinfo.h:28
@ LittleEndian
Definition qsysinfo.h:30
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR uint qPopulationCount(quint32 v) noexcept
const int blockSize
QDebug operator<<(QDebug dbg, const QBitArray &array)
static bool testBit(long bit, const long *field)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat n
const GLubyte * c
GLenum array
GLenum GLsizei len
GLuint in
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
#define a2
#define a1
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
unsigned long long quint64
Definition qtypes.h:56
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned char quint8
Definition qtypes.h:41
QByteArray ba
[0]
QTextStream out(stdout)
[7]
QDataStream & operator>>(QDataStream &in, MyClass &myObj)
QSharedPointer< T > other(t)
[5]