Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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// Qt-Security score:significant reason:default
5
6#include "qbitarray.h"
7#include <qalgorithms.h>
8#include <qdatastream.h>
9#include <qdebug.h>
10#include <qendian.h>
11
12#include <limits>
13
14#include <string.h>
15
17
18/*!
19 \class QBitArray
20 \inmodule QtCore
21 \brief The QBitArray class provides an array of bits.
22
23 \ingroup tools
24 \ingroup shared
25 \reentrant
26
27 \compares equality
28
29 A QBitArray is an array that gives access to individual bits and
30 provides operators (\l{operator&()}{AND}, \l{operator|()}{OR},
31 \l{operator^()}{XOR}, and \l{operator~()}{NOT}) that work on
32 entire arrays of bits. It uses \l{implicit sharing} (copy-on-write)
33 to reduce memory usage and to avoid the needless copying of data.
34
35 The following code constructs a QBitArray containing 200 bits
36 initialized to false (0):
37
38 \snippet code/src_corelib_tools_qbitarray.cpp 0
39
40 To initialize the bits to true, either pass \c true as second
41 argument to the constructor, or call fill() later on.
42
43 QBitArray uses 0-based indexes, just like C++ arrays. To access
44 the bit at a particular index position, you can use operator[]().
45 On non-const bit arrays, operator[]() returns a reference to a
46 bit that can be used on the left side of an assignment. For
47 example:
48
49 \snippet code/src_corelib_tools_qbitarray.cpp 1
50
51 For technical reasons, it is more efficient to use testBit() and
52 setBit() to access bits in the array than operator[](). For
53 example:
54
55 \snippet code/src_corelib_tools_qbitarray.cpp 2
56
57 QBitArray supports \c{&} (\l{operator&()}{AND}), \c{|}
58 (\l{operator|()}{OR}), \c{^} (\l{operator^()}{XOR}),
59 \c{~} (\l{operator~()}{NOT}), as well as
60 \c{&=}, \c{|=}, and \c{^=}. These operators work in the same way
61 as the built-in C++ bitwise operators of the same name. For
62 example:
63
64 \snippet code/src_corelib_tools_qbitarray.cpp 3
65
66 For historical reasons, QBitArray distinguishes between a null
67 bit array and an empty bit array. A \e null bit array is a bit
68 array that is initialized using QBitArray's default constructor.
69 An \e empty bit array is any bit array with size 0. A null bit
70 array is always empty, but an empty bit array isn't necessarily
71 null:
72
73 \snippet code/src_corelib_tools_qbitarray.cpp 4
74
75 All functions except isNull() treat null bit arrays the same as
76 empty bit arrays; for example, QBitArray() compares equal to
77 QBitArray(0). We recommend that you always use isEmpty() and
78 avoid isNull().
79
80 \sa QByteArray, QList
81*/
82
83#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
84/*!
85 \fn QBitArray::QBitArray(QBitArray &&other)
86
87 Move-constructs a QBitArray instance, making it point at the same
88 object that \a other was pointing to.
89
90 \since 5.2
91*/
92#endif
93
94/*! \fn QBitArray::QBitArray()
95
96 Constructs an empty bit array.
97
98 \sa isEmpty()
99*/
100
101/*
102 * QBitArray construction note:
103 *
104 * We overallocate the byte array by 1 byte. The first user bit is at
105 * d.data()[1]. On the extra first byte, we store the difference between the
106 * number of bits in the byte array (including this byte) and the number of
107 * bits in the bit array. Therefore, for a non-empty QBitArray, it's always a
108 * number between 8 and 15. For the empty one, d is the an empty QByteArray and
109 * *d.constData() is the QByteArray's terminating NUL (0) byte.
110 *
111 * This allows for fast calculation of the bit array size:
112 * inline qsizetype size() const { return (d.size() << 3) - *d.constData(); }
113 */
114
115static constexpr qsizetype storage_size(qsizetype size)
116{
117 // avoid overflow when adding 7, by doing the arithmetic in unsigned space:
118 return qsizetype((size_t(size) + 7) / 8);
119}
120
121static constexpr qsizetype allocation_size(qsizetype size)
122{
123 return size <= 0 ? 0 : storage_size(size) + 1;
124}
125
126static void adjust_head_and_tail(char *data, qsizetype storageSize, qsizetype logicalSize)
127{
128 quint8 *c = reinterpret_cast<quint8 *>(data);
129 // store the difference between storage and logical size in d[0]:
130 *c = quint8(size_t(storageSize) * 8 - logicalSize);
131 // reset unallocated bits to 0:
132 if (logicalSize & 7)
133 *(c + 1 + logicalSize / 8) &= (1 << (logicalSize & 7)) - 1;
134}
135
136/*!
137 Constructs a bit array containing \a size bits. The bits are
138 initialized with \a value, which defaults to false (0).
139*/
140QBitArray::QBitArray(qsizetype size, bool value)
141 : d(allocation_size(size), value ? 0xFF : 0x00)
142{
143 Q_ASSERT_X(size >= 0, "QBitArray::QBitArray", "Size must be greater than or equal to 0.");
144 if (size <= 0)
145 return;
146
147 adjust_head_and_tail(d.data(), d.size(), size);
148}
149
150/*! \fn qsizetype QBitArray::size() const
151
152 Returns the number of bits stored in the bit array.
153
154 \sa resize()
155*/
156
157/*! \fn qsizetype QBitArray::count() const
158
159 Same as size().
160*/
161
162/*!
163 If \a on is true, this function returns the number of
164 1-bits stored in the bit array; otherwise the number
165 of 0-bits is returned.
166*/
167qsizetype QBitArray::count(bool on) const
168{
169 qsizetype numBits = 0;
170 const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
171
172 // the loops below will try to read from *end
173 // it's the QByteArray implicit NUL, so it will not change the bit count
174 const quint8 *const end = reinterpret_cast<const quint8 *>(d.end());
175
176 while (bits + 7 <= end) {
177 quint64 v = qFromUnaligned<quint64>(bits);
178 bits += 8;
179 numBits += qsizetype(qPopulationCount(v));
180 }
181 if (bits + 3 <= end) {
182 quint32 v = qFromUnaligned<quint32>(bits);
183 bits += 4;
184 numBits += qsizetype(qPopulationCount(v));
185 }
186 if (bits + 1 < end) {
187 quint16 v = qFromUnaligned<quint16>(bits);
188 bits += 2;
189 numBits += qsizetype(qPopulationCount(v));
190 }
191 if (bits < end)
192 numBits += qsizetype(qPopulationCount(bits[0]));
193
194 return on ? numBits : size() - numBits;
195}
196
197/*!
198 Resizes the bit array to \a size bits.
199
200 If \a size is greater than the current size, the bit array is
201 extended to make it \a size bits with the extra bits added to the
202 end. The new bits are initialized to false (0).
203
204 If \a size is less than the current size, bits are removed from
205 the end.
206
207 \sa size()
208*/
209void QBitArray::resize(qsizetype size)
210{
211 Q_ASSERT_X(size >= 0, "QBitArray::resize", "Size must be greater than or equal to 0.");
212 if (size <= 0) {
213 d.resize(0);
214 } else {
215 d.resize(allocation_size(size), 0x00);
216 adjust_head_and_tail(d.data(), d.size(), size);
217 }
218}
219
220/*! \fn bool QBitArray::isEmpty() const
221
222 Returns \c true if this bit array has size 0; otherwise returns
223 false.
224
225 \sa size()
226*/
227
228/*! \fn bool QBitArray::isNull() const
229
230 Returns \c true if this bit array is null; otherwise returns \c false.
231
232 Example:
233 \snippet code/src_corelib_tools_qbitarray.cpp 5
234
235 Qt makes a distinction between null bit arrays and empty bit
236 arrays for historical reasons. For most applications, what
237 matters is whether or not a bit array contains any data,
238 and this can be determined using isEmpty().
239
240 \sa isEmpty()
241*/
242
243/*! \fn bool QBitArray::fill(bool value, qsizetype size = -1)
244
245 Sets every bit in the bit array to \a value, returning true if successful;
246 otherwise returns \c false. If \a size is different from -1 (the default),
247 the bit array is resized to \a size beforehand.
248
249 Example:
250 \snippet code/src_corelib_tools_qbitarray.cpp 6
251
252 \sa resize()
253*/
254
255/*!
256 \overload
257
258 Sets bits at index positions \a begin up to (but not including) \a end
259 to \a value.
260
261 \a begin must be a valid index position in the bit array
262 (0 <= \a begin < size()).
263
264 \a end must be either a valid index position or equal to size(), in
265 which case the fill operation runs until the end of the array
266 (0 <= \a end <= size()).
267
268 Example:
269 \snippet code/src_corelib_tools_qbitarray.cpp 15
270*/
271
272void QBitArray::fill(bool value, qsizetype begin, qsizetype end)
273{
274 while (begin < end && begin & 0x7)
275 setBit(begin++, value);
276 qsizetype len = end - begin;
277 if (len <= 0)
278 return;
279 qsizetype s = len & ~qsizetype(0x7);
280 uchar *c = reinterpret_cast<uchar *>(d.data());
281 memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
282 begin += s;
283 while (begin < end)
284 setBit(begin++, value);
285}
286
287/*!
288 \fn const char *QBitArray::bits() const
289 \since 5.11
290
291 Returns a pointer to a dense bit array for this QBitArray. Bits are counted
292 upwards from the least significant bit in each byte. The number of bits
293 relevant in the last byte is given by \c{size() % 8}.
294
295 \sa fromBits(), size()
296 */
297
298/*!
299 \since 5.11
300
301 Creates a QBitArray with the dense bit array located at \a data, with \a
302 size bits. The byte array at \a data must be at least \a size / 8 (rounded up)
303 bytes long.
304
305 If \a size is not a multiple of 8, this function will include the lowest
306 \a size % 8 bits from the last byte in \a data.
307
308 \sa bits()
309 */
310QBitArray QBitArray::fromBits(const char *data, qsizetype size)
311{
312 Q_ASSERT_X(size >= 0, "QBitArray::fromBits", "Size must be greater than or equal to 0.");
313 QBitArray result;
314 if (size <= 0)
315 return result;
316
317 auto &d = result.d;
318 d.resize(allocation_size(size));
319 memcpy(d.data() + 1, data, d.size() - 1);
320 adjust_head_and_tail(d.data(), d.size(), size);
321 return result;
322}
323
324/*!
325 \since 6.0
326
327 Returns the array of bit converted to an int. The conversion is based on \a endianness.
328 Converts up to the first 32 bits of the array to \c quint32 and returns it,
329 obeying \a endianness. If \a ok is not a null pointer, and the array has more
330 than 32 bits, \a ok is set to false and this function returns zero; otherwise,
331 it's set to true.
332*/
333quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcept
334{
335 const qsizetype _size = size();
336 if (_size > 32) {
337 if (ok)
338 *ok = false;
339 return 0;
340 }
341
342 if (ok)
343 *ok = true;
344
345 quint32 factor = 1;
346 quint32 total = 0;
347 for (qsizetype i = 0; i < _size; ++i, factor *= 2) {
348 const auto index = endianness == QSysInfo::Endian::LittleEndian ? i : (_size - i - 1);
349 if (testBit(index))
350 total += factor;
351 }
352
353 return total;
354}
355
356/*! \fn bool QBitArray::isDetached() const
357
358 \internal
359*/
360
361/*! \fn void QBitArray::detach()
362
363 \internal
364*/
365
366/*! \fn void QBitArray::clear()
367
368 Clears the contents of the bit array and makes it empty.
369
370 \sa resize(), isEmpty()
371*/
372
373/*! \fn void QBitArray::truncate(qsizetype pos)
374
375 Truncates the bit array at index position \a pos.
376
377 If \a pos is beyond the end of the array, nothing happens.
378
379 \sa resize()
380*/
381
382/*! \fn bool QBitArray::toggleBit(qsizetype i)
383
384 Inverts the value of the bit at index position \a i, returning the
385 previous value of that bit as either true (if it was set) or false (if
386 it was unset).
387
388 If the previous value was 0, the new value will be 1. If the
389 previous value was 1, the new value will be 0.
390
391 \a i must be a valid index position in the bit array (i.e., 0 <=
392 \a i < size()).
393
394 \sa setBit(), clearBit()
395*/
396
397/*! \fn bool QBitArray::testBit(qsizetype i) const
398
399 Returns \c true if the bit at index position \a i is 1; otherwise
400 returns \c false.
401
402 \a i must be a valid index position in the bit array (i.e., 0 <=
403 \a i < size()).
404
405 \sa setBit(), clearBit()
406*/
407
408/*! \fn bool QBitArray::setBit(qsizetype i)
409
410 Sets the bit at index position \a i to 1.
411
412 \a i must be a valid index position in the bit array (i.e., 0 <=
413 \a i < size()).
414
415 \sa clearBit(), toggleBit()
416*/
417
418/*! \fn void QBitArray::setBit(qsizetype i, bool value)
419
420 \overload
421
422 Sets the bit at index position \a i to \a value.
423*/
424
425/*! \fn void QBitArray::clearBit(qsizetype i)
426
427 Sets the bit at index position \a i to 0.
428
429 \a i must be a valid index position in the bit array (i.e., 0 <=
430 \a i < size()).
431
432 \sa setBit(), toggleBit()
433*/
434
435/*! \fn bool QBitArray::at(qsizetype i) const
436
437 Returns the value of the bit at index position \a i.
438
439 \a i must be a valid index position in the bit array (i.e., 0 <=
440 \a i < size()).
441
442 \sa operator[]()
443*/
444
445/*! \fn QBitRef QBitArray::operator[](qsizetype i)
446
447 Returns the bit at index position \a i as a modifiable reference.
448
449 \a i must be a valid index position in the bit array (i.e., 0 <=
450 \a i < size()).
451
452 Example:
453 \snippet code/src_corelib_tools_qbitarray.cpp 7
454
455 The return value is of type QBitRef, a helper class for QBitArray.
456 When you get an object of type QBitRef, you can assign to
457 it, and the assignment will apply to the bit in the QBitArray
458 from which you got the reference.
459
460 The functions testBit(), setBit(), and clearBit() are slightly
461 faster.
462
463 \sa at(), testBit(), setBit(), clearBit()
464*/
465
466/*! \fn bool QBitArray::operator[](qsizetype i) const
467
468 \overload
469*/
470
471#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
472/*! \fn QBitArray::QBitArray(const QBitArray &other) noexcept
473
474 Constructs a copy of \a other.
475
476 This operation takes \l{constant time}, because QBitArray is
477 \l{implicitly shared}. This makes returning a QBitArray from a
478 function very fast. If a shared instance is modified, it will be
479 copied (copy-on-write), and that takes \l{linear time}.
480
481 \sa operator=()
482*/
483
484/*! \fn QBitArray &QBitArray::operator=(const QBitArray &other) noexcept
485
486 Assigns \a other to this bit array and returns a reference to
487 this bit array.
488*/
489
490/*! \fn QBitArray &QBitArray::operator=(QBitArray &&other)
491 \since 5.2
492
493 Moves \a other to this bit array and returns a reference to
494 this bit array.
495*/
496#endif // Qt 6
497
498/*! \fn void QBitArray::swap(QBitArray &other)
499 \since 4.8
500 \memberswap{bit array}
501*/
502
503/*! \fn bool QBitArray::operator==(const QBitArray &lhs, const QBitArray &rhs)
504
505 Returns \c true if \a lhs is equal to \a rhs bit array; otherwise
506 returns \c false.
507
508 \sa operator!=()
509*/
510
511/*! \fn bool QBitArray::operator!=(const QBitArray &lhs, const QBitArray &rhs)
512
513 Returns \c true if \a lhs is not equal to \a rhs bit array;
514 otherwise returns \c false.
515
516 \sa operator==()
517*/
518
519// Returns a new QBitArray that has the same size as the bigger of \a a1 and
520// \a a2, but whose contents are uninitialized.
521static QBitArray sizedForOverwrite(const QBitArray &a1, const QBitArray &a2)
522{
523 QBitArray result;
524 const QByteArrayData &d1 = a1.data_ptr();
525 const QByteArrayData &d2 = a2.data_ptr();
526 qsizetype n1 = d1.size;
527 qsizetype n2 = d2.size;
528 qsizetype n = qMax(n1, n2);
529
530 QByteArrayData bytes(n, n);
531
532 // initialize the count of bits in the last byte (see construction note)
533 // and the QByteArray null termination (some of our algorithms read it)
534 if (n1 > n2) {
535 *bytes.ptr = *d1.ptr;
536 bytes.ptr[n1] = 0;
537 } else if (n2 > n1) {
538 *bytes.ptr = *d2.ptr;
539 bytes.ptr[n2] = 0;
540 } else if (n1) { // n1 == n2
541 *bytes.ptr = qMin(*d1.ptr, *d2.ptr);
542 bytes.ptr[n1] = 0;
543 }
544
545 result.data_ptr() = std::move(bytes);
546 return result;
547}
548
549template <typename BitwiseOp> Q_NEVER_INLINE static
550QBitArray &performBitwiseOperationHelper(QBitArray &out, const QBitArray &a1,
551 const QBitArray &a2, BitwiseOp op)
552{
553 const QByteArrayData &d1 = a1.data_ptr();
554 const QByteArrayData &d2 = a2.data_ptr();
555
556 // Sizes in bytes (including the initial bit difference counter)
557 qsizetype n1 = d1.size;
558 qsizetype n2 = d2.size;
559 Q_ASSERT(out.data_ptr().size == qMax(n1, n2));
560 Q_ASSERT(out.data_ptr().size == 0 || !out.data_ptr().needsDetach());
561
562 // Bypass QByteArray's emptiness verification; we won't dereference
563 // these pointers if their size is zero.
564 auto dst = reinterpret_cast<uchar *>(out.data_ptr().data());
565 auto p1 = reinterpret_cast<const uchar *>(d1.data());
566 auto p2 = reinterpret_cast<const uchar *>(d2.data());
567
568 // Main: perform the operation in the range where both arrays have data
569 if (n1 < n2) {
570 std::swap(n1, n2);
571 std::swap(p1, p2);
572 }
573 for (qsizetype i = 1; i < n2; ++i)
574 dst[i] = op(p1[i], p2[i]);
575
576 // Tail: operate as if both arrays had the same data by padding zeroes to
577 // the end of the shorter of the two (for std::bit_or and std::bit_xor, this is
578 // a memmove; for std::bit_and, it's memset to 0).
579 for (qsizetype i = qMax(n2, qsizetype(1)); i < n1; ++i)
580 dst[i] = op(p1[i], uchar(0));
581
582 return out;
583}
584
585template <typename BitwiseOp> Q_NEVER_INLINE static
586QBitArray &performBitwiseOperationInCopy(QBitArray &self, const QBitArray &other, BitwiseOp op)
587{
588 QBitArray tmp(std::move(self));
589 self = sizedForOverwrite(tmp, other);
590 return performBitwiseOperationHelper(self, tmp, other, op);
591}
592
593template <typename BitwiseOp> Q_NEVER_INLINE static
594QBitArray &performBitwiseOperationInPlace(QBitArray &self, const QBitArray &other, BitwiseOp op)
595{
596 if (self.size() < other.size())
597 self.resize(other.size());
598 return performBitwiseOperationHelper(self, self, other, op);
599}
600
601template <typename BitwiseOp> static
602QBitArray &performBitwiseOperation(QBitArray &self, const QBitArray &other, BitwiseOp op)
603{
604 if (self.data_ptr().needsDetach())
605 return performBitwiseOperationInCopy(self, other, op);
606 return performBitwiseOperationInPlace(self, other, op);
607}
608
609// SCARY helper
610enum { InCopy, InPlace };
611static auto prepareForBitwiseOperation(QBitArray &self, QBitArray &other)
612{
613 QByteArrayData &d1 = self.data_ptr();
614 QByteArrayData &d2 = other.data_ptr();
615 bool detached1 = !d1.needsDetach();
616 bool detached2 = !d2.needsDetach();
617 if (!detached1 && !detached2)
618 return InCopy;
619
620 // at least one of the two is detached, we'll reuse its buffer
621 bool swap = false;
622 if (detached1 && detached2) {
623 // both are detached, so choose the larger of the two
624 swap = d1.allocatedCapacity() < d2.allocatedCapacity();
625 } else if (detached2) {
626 // we can re-use other's buffer but not self's, so swap the two
627 swap = true;
628 }
629 if (swap)
630 self.swap(other);
631 return InPlace;
632}
633
634template <typename BitwiseOp> static
635QBitArray &performBitwiseOperation(QBitArray &self, QBitArray &other, BitwiseOp op)
636{
637 auto choice = prepareForBitwiseOperation(self, other);
638 if (choice == InCopy)
639 return performBitwiseOperationInCopy(self, other, std::move(op));
640 return performBitwiseOperationInPlace(self, other, std::move(op));
641}
642
643/*!
644 \fn QBitArray &QBitArray::operator&=(const QBitArray &other)
645 \fn QBitArray &QBitArray::operator&=(QBitArray &&other)
646
647 Performs the AND operation between all bits in this bit array and
648 \a other. Assigns the result to this bit array, and returns a
649 reference to it.
650
651 The result has the length of the longest of the two bit arrays,
652 with any missing bits (if one array is shorter than the other)
653 taken to be 0.
654
655 Example:
656 \snippet code/src_corelib_tools_qbitarray.cpp 8
657
658 \sa operator&(), operator|=(), operator^=(), operator~()
659*/
660
661QBitArray &QBitArray::operator&=(QBitArray &&other)
662{
663 return performBitwiseOperation(*this, other, std::bit_and<uchar>());
664}
665
666QBitArray &QBitArray::operator&=(const QBitArray &other)
667{
668 return performBitwiseOperation(*this, other, std::bit_and<uchar>());
669}
670
671/*!
672 \fn QBitArray &QBitArray::operator|=(const QBitArray &other)
673 \fn QBitArray &QBitArray::operator|=(QBitArray &&other)
674
675 Performs the OR operation between all bits in this bit array and
676 \a other. Assigns the result to this bit array, and returns a
677 reference to it.
678
679 The result has the length of the longest of the two bit arrays,
680 with any missing bits (if one array is shorter than the other)
681 taken to be 0.
682
683 Example:
684 \snippet code/src_corelib_tools_qbitarray.cpp 9
685
686 \sa operator|(), operator&=(), operator^=(), operator~()
687*/
688
689QBitArray &QBitArray::operator|=(QBitArray &&other)
690{
691 return performBitwiseOperation(*this, other, std::bit_or<uchar>());
692}
693
694QBitArray &QBitArray::operator|=(const QBitArray &other)
695{
696 return performBitwiseOperation(*this, other, std::bit_or<uchar>());
697}
698
699/*!
700 \fn QBitArray &QBitArray::operator^=(const QBitArray &other)
701 \fn QBitArray &QBitArray::operator^=(QBitArray &&other)
702
703 Performs the XOR operation between all bits in this bit array and
704 \a other. Assigns the result to this bit array, and returns a
705 reference to it.
706
707 The result has the length of the longest of the two bit arrays,
708 with any missing bits (if one array is shorter than the other)
709 taken to be 0.
710
711 Example:
712 \snippet code/src_corelib_tools_qbitarray.cpp 10
713
714 \sa operator^(), operator&=(), operator|=(), operator~()
715*/
716
717QBitArray &QBitArray::operator^=(QBitArray &&other)
718{
719 return performBitwiseOperation(*this, other, std::bit_xor<uchar>());
720}
721
722QBitArray &QBitArray::operator^=(const QBitArray &other)
723{
724 return performBitwiseOperation(*this, other, std::bit_xor<uchar>());
725}
726
727/*!
728 \fn QBitArray QBitArray::operator~(QBitArray a)
729 Returns a bit array that contains the inverted bits of the bit
730 array \a a.
731
732 Example:
733 \snippet code/src_corelib_tools_qbitarray.cpp 11
734
735 \sa operator&(), operator|(), operator^()
736*/
737
738Q_NEVER_INLINE QBitArray QBitArray::inverted_inplace() &&
739{
740 qsizetype n = d.size();
741 uchar *dst = reinterpret_cast<uchar *>(data_ptr().data());
742 const uchar *src = dst;
743 QBitArray result([&] {
744 if (d.isDetached() || n == 0)
745 return std::move(d.data_ptr()); // invert in-place
746
747 QByteArrayData tmp(n, n);
748 dst = reinterpret_cast<uchar *>(tmp.data());
749 return tmp;
750 }());
751
752 uchar bitdiff = 8;
753 if (n)
754 bitdiff = dst[0] = src[0]; // copy the count of bits in the last byte
755
756 for (qsizetype i = 1; i < n; ++i)
757 dst[i] = ~src[i];
758
759 if (int tailCount = 16 - bitdiff; tailCount != 8) {
760 // zero the bits beyond our size in the last byte
761 Q_ASSERT(n > 1);
762 uchar tailMask = (1U << tailCount) - 1;
763 dst[n - 1] &= tailMask;
764 }
765
766 return result;
767}
768
769/*!
770 \fn QBitArray QBitArray::operator&(const QBitArray &a1, const QBitArray &a2)
771 \fn QBitArray QBitArray::operator&(QBitArray &&a1, const QBitArray &a2)
772 \fn QBitArray QBitArray::operator&(const QBitArray &a1, QBitArray &&a2)
773 \fn QBitArray QBitArray::operator&(QBitArray &&a1, QBitArray &&a2)
774
775 Returns a bit array that is the AND of the bit arrays \a a1 and \a
776 a2.
777
778 The result has the length of the longest of the two bit arrays,
779 with any missing bits (if one array is shorter than the other)
780 taken to be 0.
781
782 Example:
783 \snippet code/src_corelib_tools_qbitarray.cpp 12
784
785 \sa {QBitArray::}{operator&=()}, {QBitArray::}{operator|()}, {QBitArray::}{operator^()}
786*/
787
788QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
789{
790 QBitArray tmp = sizedForOverwrite(a1, a2);
791 performBitwiseOperationHelper(tmp, a1, a2, std::bit_and<uchar>());
792 return tmp;
793}
794
795/*!
796 \fn QBitArray QBitArray::operator|(const QBitArray &a1, const QBitArray &a2)
797 \fn QBitArray QBitArray::operator|(QBitArray &&a1, const QBitArray &a2)
798 \fn QBitArray QBitArray::operator|(const QBitArray &a1, QBitArray &&a2)
799 \fn QBitArray QBitArray::operator|(QBitArray &&a1, QBitArray &&a2)
800
801 Returns a bit array that is the OR of the bit arrays \a a1 and \a
802 a2.
803
804 The result has the length of the longest of the two bit arrays,
805 with any missing bits (if one array is shorter than the other)
806 taken to be 0.
807
808 Example:
809 \snippet code/src_corelib_tools_qbitarray.cpp 13
810
811 \sa QBitArray::operator|=(), operator&(), operator^()
812*/
813
814QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
815{
816 QBitArray tmp = sizedForOverwrite(a1, a2);
817 performBitwiseOperationHelper(tmp, a1, a2, std::bit_or<uchar>());
818 return tmp;
819}
820
821/*!
822 \fn QBitArray QBitArray::operator^(const QBitArray &a1, const QBitArray &a2)
823 \fn QBitArray QBitArray::operator^(QBitArray &&a1, const QBitArray &a2)
824 \fn QBitArray QBitArray::operator^(const QBitArray &a1, QBitArray &&a2)
825 \fn QBitArray QBitArray::operator^(QBitArray &&a1, QBitArray &&a2)
826
827 Returns a bit array that is the XOR of the bit arrays \a a1 and \a
828 a2.
829
830 The result has the length of the longest of the two bit arrays,
831 with any missing bits (if one array is shorter than the other)
832 taken to be 0.
833
834 Example:
835 \snippet code/src_corelib_tools_qbitarray.cpp 14
836
837 \sa {QBitArray}{operator^=()}, {QBitArray}{operator&()}, {QBitArray}{operator|()}
838*/
839
840QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
841{
842 QBitArray tmp = sizedForOverwrite(a1, a2);
843 performBitwiseOperationHelper(tmp, a1, a2, std::bit_xor<uchar>());
844 return tmp;
845}
846
847/*!
848 \class QBitRef
849 \inmodule QtCore
850 \reentrant
851 \brief The QBitRef class is an internal class, used with QBitArray.
852
853 \internal
854
855 The QBitRef is required by the indexing [] operator on bit arrays.
856 It is not for use in any other context.
857*/
858
859/*! \fn QBitRef::QBitRef (QBitArray& a, qsizetype i)
860
861 Constructs a reference to element \a i in the QBitArray \a a.
862 This is what QBitArray::operator[] constructs its return value
863 with.
864*/
865
866/*! \fn QBitRef::operator bool() const
867
868 Returns the value referenced by the QBitRef.
869*/
870
871/*! \fn bool QBitRef::operator!() const
872
873 \internal
874*/
875
876/*! \fn QBitRef& QBitRef::operator= (const QBitRef& v)
877
878 Sets the value referenced by the QBitRef to that referenced by
879 QBitRef \a v.
880*/
881
882/*! \fn QBitRef& QBitRef::operator= (bool v)
883 \overload
884
885 Sets the value referenced by the QBitRef to \a v.
886*/
887
888/*****************************************************************************
889 QBitArray stream functions
890 *****************************************************************************/
891
892#ifndef QT_NO_DATASTREAM
893/*!
894 \relates QBitArray
895
896 Writes bit array \a ba to stream \a out.
897
898 \sa {Serializing Qt Data Types}{Format of the QDataStream operators}
899*/
900
901QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
902{
903 const qsizetype len = ba.size();
904 if (out.version() < QDataStream::Qt_6_0) {
905 if (Q_UNLIKELY(len > qsizetype{(std::numeric_limits<qint32>::max)()})) {
906 out.setStatus(QDataStream::Status::SizeLimitExceeded);
907 return out;
908 }
909 out << quint32(len);
910 } else {
911 out << quint64(len);
912 }
913 if (len > 0)
914 out.writeRawData(ba.d.data() + 1, ba.d.size() - 1);
915 return out;
916}
917
918/*!
919 \relates QBitArray
920
921 Reads a bit array into \a ba from stream \a in.
922
923 \sa {Serializing Qt Data Types}{Format of the QDataStream operators}
924*/
925
926QDataStream &operator>>(QDataStream &in, QBitArray &ba)
927{
928 ba.clear();
929 qsizetype len;
930 if (in.version() < QDataStream::Qt_6_0) {
931 quint32 tmp;
932 in >> tmp;
933 if (Q_UNLIKELY(tmp > quint32((std::numeric_limits<qint32>::max)()))) {
934 in.setStatus(QDataStream::ReadCorruptData);
935 return in;
936 }
937 len = tmp;
938 } else {
939 quint64 tmp;
940 in >> tmp;
941 if (Q_UNLIKELY(tmp > quint64((std::numeric_limits<qsizetype>::max)()))) {
942 in.setStatus(QDataStream::Status::SizeLimitExceeded);
943 return in;
944 }
945 len = tmp;
946 }
947 if (len == 0) {
948 ba.clear();
949 return in;
950 }
951
952 const qsizetype Step = 8 * 1024 * 1024;
953 const qsizetype totalBytes = storage_size(len);
954 qsizetype allocated = 0;
955
956 while (allocated < totalBytes) {
957 qsizetype blockSize = qMin(Step, totalBytes - allocated);
958 ba.d.resize(allocated + blockSize + 1);
959 if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
960 ba.clear();
961 in.setStatus(QDataStream::ReadPastEnd);
962 return in;
963 }
964 allocated += blockSize;
965 }
966
967 const auto fromStream = ba.d.back();
968 adjust_head_and_tail(ba.d.data(), ba.d.size(), len);
969 if (ba.d.back() != fromStream) {
970 ba.clear();
971 in.setStatus(QDataStream::ReadCorruptData);
972 return in;
973 }
974 return in;
975}
976#endif // QT_NO_DATASTREAM
977
978#ifndef QT_NO_DEBUG_STREAM
979QDebug operator<<(QDebug dbg, const QBitArray &array)
980{
981 QDebugStateSaver saver(dbg);
982 dbg.nospace() << "QBitArray(";
983 for (qsizetype i = 0; i < array.size();) {
984 if (array.testBit(i))
985 dbg << '1';
986 else
987 dbg << '0';
988 i += 1;
989 if (!(i % 4) && (i < array.size()))
990 dbg << ' ';
991 }
992 dbg << ')';
993 return dbg;
994}
995#endif
996
997/*!
998 \fn DataPtr &QBitArray::data_ptr()
999 \internal
1000*/
1001
1002/*!
1003 \typedef QBitArray::DataPtr
1004 \internal
1005*/
1006
1007QT_END_NAMESPACE
\inmodule QtCore
Definition qbitarray.h:14
Combined button and popup list for selecting options.
static constexpr qsizetype storage_size(qsizetype size)
static QBitArray sizedForOverwrite(const QBitArray &a1, const QBitArray &a2)
QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
static constexpr qsizetype allocation_size(qsizetype size)
static void adjust_head_and_tail(char *data, qsizetype storageSize, qsizetype logicalSize)
QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
static auto prepareForBitwiseOperation(QBitArray &self, QBitArray &other)
@ InPlace
@ InCopy
QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
static QBitArray & performBitwiseOperation(QBitArray &self, const QBitArray &other, BitwiseOp op)
QDataStream & operator>>(QDataStream &s, QKeyCombination &combination)
QDebug operator<<(QDebug dbg, const QFileInfo &fi)