QtBase  v6.3.1
qbitarray.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Copyright (C) 2019 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qbitarray.h"
42 #include <qalgorithms.h>
43 #include <qdatastream.h>
44 #include <qdebug.h>
45 #include <qendian.h>
46 #include <string.h>
47 
49 
129 /*
130  * QBitArray construction note:
131  *
132  * We overallocate the byte array by 1 byte. The first user bit is at
133  * d.data()[1]. On the extra first byte, we store the difference between the
134  * number of bits in the byte array (including this byte) and the number of
135  * bits in the bit array. Therefore, for a non-empty QBitArray, it's always a
136  * number between 8 and 15. For the empty one, d is the an empty QByteArray and
137  * *d.constData() is the QByteArray's terminating NUL (0) byte.
138  *
139  * This allows for fast calculation of the bit array size:
140  * inline qsizetype size() const { return (d.size() << 3) - *d.constData(); }
141  */
142 
148  : d(size <= 0 ? 0 : 1 + (size + 7) / 8, Qt::Uninitialized)
149 {
150  Q_ASSERT_X(size >= 0, "QBitArray::QBitArray", "Size must be greater than or equal to 0.");
151  if (size <= 0)
152  return;
153 
154  uchar *c = reinterpret_cast<uchar *>(d.data());
155  memset(c + 1, value ? 0xff : 0, d.size() - 1);
156  *c = d.size() * 8 - size;
157  if (value && size && size & 7)
158  *(c + 1 + size / 8) &= (1 << (size & 7)) - 1;
159 }
160 
179 {
180  qsizetype numBits = 0;
181  const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
182 
183  // the loops below will try to read from *end
184  // it's the QByteArray implicit NUL, so it will not change the bit count
185  const quint8 *const end = reinterpret_cast<const quint8 *>(d.end());
186 
187  while (bits + 7 <= end) {
188  quint64 v = qFromUnaligned<quint64>(bits);
189  bits += 8;
190  numBits += qsizetype(qPopulationCount(v));
191  }
192  if (bits + 3 <= end) {
193  quint32 v = qFromUnaligned<quint32>(bits);
194  bits += 4;
195  numBits += qsizetype(qPopulationCount(v));
196  }
197  if (bits + 1 < end) {
198  quint16 v = qFromUnaligned<quint16>(bits);
199  bits += 2;
200  numBits += qsizetype(qPopulationCount(v));
201  }
202  if (bits < end)
203  numBits += qsizetype(qPopulationCount(bits[0]));
204 
205  return on ? numBits : size() - numBits;
206 }
207 
221 {
222  if (!size) {
223  d.resize(0);
224  } else {
225  qsizetype s = d.size();
226  d.resize(1 + (size + 7) / 8);
227  uchar *c = reinterpret_cast<uchar *>(d.data());
228  if (size > (s << 3))
229  memset(c + s, 0, d.size() - s);
230  else if (size & 7)
231  *(c + 1 + size / 8) &= (1 << (size & 7)) - 1;
232  *c = d.size() * 8 - size;
233  }
234 }
235 
289 {
290  while (begin < end && begin & 0x7)
291  setBit(begin++, value);
292  qsizetype len = end - begin;
293  if (len <= 0)
294  return;
295  qsizetype s = len & ~qsizetype(0x7);
296  uchar *c = reinterpret_cast<uchar *>(d.data());
297  memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
298  begin += s;
299  while (begin < end)
300  setBit(begin++, value);
301 }
302 
327 {
329  if (size == 0)
330  return result;
331  qsizetype nbytes = (size + 7) / 8;
332 
333  result.d = QByteArray(nbytes + 1, Qt::Uninitialized);
334  char *bits = result.d.data();
335  memcpy(bits + 1, data, nbytes);
336 
337  // clear any unused bits from the last byte
338  if (size & 7)
339  bits[nbytes] &= 0xffU >> (8 - (size & 7));
340 
341  *bits = result.d.size() * 8 - size;
342  return result;
343 }
344 
354 quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcept
355 {
356  const qsizetype _size = size();
357  if (_size > 32) {
358  if (ok)
359  *ok = false;
360  return 0;
361  }
362 
363  if (ok)
364  *ok = true;
365 
366  quint32 factor = 1;
367  quint32 total = 0;
368  for (qsizetype i = 0; i < _size; ++i, factor *= 2) {
369  const auto index = endianness == QSysInfo::Endian::LittleEndian ? i : (_size - i - 1);
370  if (testBit(index))
371  total += factor;
372  }
373 
374  return total;
375 }
376 
556 {
557  resize(qMax(size(), other.size()));
558  uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
559  const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
560  qsizetype n = other.d.size() - 1;
561  qsizetype p = d.size() - 1 - n;
562  while (n-- > 0)
563  *a1++ &= *a2++;
564  while (p-- > 0)
565  *a1++ = 0;
566  return *this;
567 }
568 
585 {
586  resize(qMax(size(), other.size()));
587  uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
588  const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
589  qsizetype n = other.d.size() - 1;
590  while (n-- > 0)
591  *a1++ |= *a2++;
592  return *this;
593 }
594 
611 {
612  resize(qMax(size(), other.size()));
613  uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
614  const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
615  qsizetype n = other.d.size() - 1;
616  while (n-- > 0)
617  *a1++ ^= *a2++;
618  return *this;
619 }
620 
632 {
633  qsizetype sz = size();
634  QBitArray a(sz);
635  const uchar *a1 = reinterpret_cast<const uchar *>(d.constData()) + 1;
636  uchar *a2 = reinterpret_cast<uchar *>(a.d.data()) + 1;
637  qsizetype n = d.size() - 1;
638 
639  while (n-- > 0)
640  *a2++ = ~*a1++;
641 
642  if (sz && sz % 8)
643  *(a2 - 1) &= (1 << (sz % 8)) - 1;
644  return a;
645 }
646 
664 {
665  QBitArray tmp = a1;
666  tmp &= a2;
667  return tmp;
668 }
669 
687 {
688  QBitArray tmp = a1;
689  tmp |= a2;
690  return tmp;
691 }
692 
710 {
711  QBitArray tmp = a1;
712  tmp ^= a2;
713  return tmp;
714 }
715 
757 /*****************************************************************************
758  QBitArray stream functions
759  *****************************************************************************/
760 
761 #ifndef QT_NO_DATASTREAM
771 {
772  if (out.version() < QDataStream::Qt_6_0) {
773  quint32 len = ba.size();
774  out << len;
775  if (len > 0)
776  out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
777  return out;
778  } else {
779  quint64 len = ba.size();
780  out << len;
781  if (len > 0)
782  out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
783  return out;
784  }
785 }
786 
796 {
797  ba.clear();
798  qsizetype len;
799  if (in.version() < QDataStream::Qt_6_0) {
800  quint32 tmp;
801  in >> tmp;
802  len = tmp;
803  } else {
804  quint64 tmp;
805  in >> tmp;
806  len = tmp;
807  }
808  if (len == 0) {
809  ba.clear();
810  return in;
811  }
812 
813  const qsizetype Step = 8 * 1024 * 1024;
814  qsizetype totalBytes = (len + 7) / 8;
815  qsizetype allocated = 0;
816 
817  while (allocated < totalBytes) {
818  qsizetype blockSize = qMin(Step, totalBytes - allocated);
819  ba.d.resize(allocated + blockSize + 1);
820  if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
821  ba.clear();
822  in.setStatus(QDataStream::ReadPastEnd);
823  return in;
824  }
825  allocated += blockSize;
826  }
827 
828  qsizetype paddingMask = ~((0x1 << (len & 0x7)) - 1);
829  if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) {
830  ba.clear();
831  in.setStatus(QDataStream::ReadCorruptData);
832  return in;
833  }
834 
835  *ba.d.data() = ba.d.size() * 8 - len;
836  return in;
837 }
838 #endif // QT_NO_DATASTREAM
839 
840 #ifndef QT_NO_DEBUG_STREAM
842 {
843  QDebugStateSaver saver(dbg);
844  dbg.nospace() << "QBitArray(";
845  for (qsizetype i = 0; i < array.size();) {
846  if (array.testBit(i))
847  dbg << '1';
848  else
849  dbg << '0';
850  i += 1;
851  if (!(i % 4) && (i < array.size()))
852  dbg << ' ';
853  }
854  dbg << ')';
855  return dbg;
856 }
857 #endif
858 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QBitArray class provides an array of bits.
Definition: qbitarray.h:49
QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
Definition: qbitarray.cpp:709
qsizetype count() const
Definition: qbitarray.h:68
QBitArray & operator|=(const QBitArray &)
Definition: qbitarray.cpp:584
void resize(qsizetype size)
Definition: qbitarray.cpp:220
void setBit(qsizetype i)
Definition: qbitarray.h:124
static QBitArray fromBits(const char *data, qsizetype len)
Definition: qbitarray.cpp:326
QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
Definition: qbitarray.cpp:686
quint32 toUInt32(QSysInfo::Endian endianness, bool *ok=nullptr) const noexcept
Definition: qbitarray.cpp:354
QBitArray & operator&=(const QBitArray &)
Definition: qbitarray.cpp:555
bool fill(bool val, qsizetype size=-1)
Definition: qbitarray.h:113
qsizetype size() const
Definition: qbitarray.h:67
QBitArray & operator^=(const QBitArray &)
Definition: qbitarray.cpp:610
QBitArray operator~() const
Definition: qbitarray.cpp:631
QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
Definition: qbitarray.cpp:663
QBitArray() noexcept
Definition: qbitarray.h:58
char * data()
Definition: qbytearray.h:516
qsizetype size() const noexcept
Definition: qbytearray.h:470
const char * constData() const noexcept
Definition: qbytearray.h:144
iterator end()
Definition: qbytearray.h:429
void clear()
void resize(qsizetype size)
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:66
operator>>(QDataStream &ds, qfloat16 &f)
Definition: qfloat16.cpp:344
operator<<(QDataStream &ds, qfloat16 f)
Definition: qfloat16.cpp:327
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
QDebug & nospace()
Definition: qdebug.h:113
Convenience class for custom QDebug operators.
Definition: qdebug.h:176
float factor
Definition: qnamespace.h:55
constexpr Initialization Uninitialized
Definition: qnamespace.h:1613
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR uint qPopulationCount(quint32 v) noexcept
Definition: qalgorithms.h:244
const int blockSize
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
unsigned int quint32
Definition: qglobal.h:288
QT_BEGIN_INCLUDE_NAMESPACE typedef unsigned char uchar
Definition: qglobal.h:332
unsigned short quint16
Definition: qglobal.h:286
unsigned long long quint64
Definition: qglobal.h:299
ptrdiff_t qsizetype
Definition: qglobal.h:308
unsigned char quint8
Definition: qglobal.h:284
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
Definition: qopenglext.h:12701
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
Definition: qopenglext.h:6904
GLenum array
Definition: qopenglext.h:7028
GLenum GLsizei len
Definition: qopenglext.h:3292
GLuint in
Definition: qopenglext.h:8870
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define Q_ASSERT_X(cond, x, msg)
Definition: qrandom.cpp:85
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
#define a2
#define a1
QByteArray ba
[0]
QTextStream out(stdout)
[7]
QSharedPointer< T > other(t)
[5]
T * data() noexcept