6#include <qalgorithms.h>
7#include <qdatastream.h>
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
82#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
84
85
86
87
88
89
90
94
95
96
97
98
101
102
103
104
105
106
107
108
109
110
111
112
117 return qsizetype((size_t(size) + 7) / 8);
122 return size <= 0 ? 0 : storage_size(size) + 1;
127 quint8 *c =
reinterpret_cast<quint8 *>(data);
129 *c = quint8(size_t(storageSize) * 8 - logicalSize);
132 *(c + 1 + logicalSize / 8) &= (1 << (logicalSize & 7)) - 1;
136
137
138
139QBitArray::QBitArray(qsizetype size,
bool value)
140 : d(allocation_size(size), value ? 0xFF : 0x00)
142 Q_ASSERT_X(size >= 0,
"QBitArray::QBitArray",
"Size must be greater than or equal to 0.");
146 adjust_head_and_tail(d.data(), d.size(), size);
150
151
152
153
154
157
158
159
162
163
164
165
166qsizetype QBitArray::count(
bool on)
const
168 qsizetype numBits = 0;
169 const quint8 *bits =
reinterpret_cast<
const quint8 *>(d.data()) + 1;
173 const quint8 *
const end =
reinterpret_cast<
const quint8 *>(d.end());
175 while (bits + 7 <= end) {
176 quint64 v = qFromUnaligned<quint64>(bits);
178 numBits += qsizetype(qPopulationCount(v));
180 if (bits + 3 <= end) {
181 quint32 v = qFromUnaligned<quint32>(bits);
183 numBits += qsizetype(qPopulationCount(v));
185 if (bits + 1 < end) {
186 quint16 v = qFromUnaligned<quint16>(bits);
188 numBits += qsizetype(qPopulationCount(v));
191 numBits += qsizetype(qPopulationCount(bits[0]));
193 return on ? numBits : size() - numBits;
197
198
199
200
201
202
203
204
205
206
207
208void QBitArray::resize(qsizetype size)
210 Q_ASSERT_X(size >= 0,
"QBitArray::resize",
"Size must be greater than or equal to 0.");
214 d.resize(allocation_size(size), 0x00);
215 adjust_head_and_tail(d.data(), d.size(), size);
220
221
222
223
224
225
228
229
230
231
232
233
234
235
236
237
238
239
240
243
244
245
246
247
248
249
250
251
252
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
271void QBitArray::fill(
bool value, qsizetype begin, qsizetype end)
273 while (begin < end && begin & 0x7)
274 setBit(begin++, value);
275 qsizetype len = end - begin;
278 qsizetype s = len & ~qsizetype(0x7);
279 uchar *c =
reinterpret_cast<uchar *>(d.data());
280 memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
283 setBit(begin++, value);
287
288
289
290
291
292
293
294
295
298
299
300
301
302
303
304
305
306
307
308
309QBitArray QBitArray::fromBits(
const char *data, qsizetype size)
311 Q_ASSERT_X(size >= 0,
"QBitArray::fromBits",
"Size must be greater than or equal to 0.");
317 d.resize(allocation_size(size));
318 memcpy(d.data() + 1, data, d.size() - 1);
319 adjust_head_and_tail(d.data(), d.size(), size);
324
325
326
327
328
329
330
331
332quint32 QBitArray::toUInt32(QSysInfo::Endian endianness,
bool *ok)
const noexcept
334 const qsizetype _size = size();
346 for (qsizetype i = 0; i < _size; ++i, factor *= 2) {
347 const auto index = endianness == QSysInfo::Endian::LittleEndian ? i : (_size - i - 1);
356
357
358
361
362
363
366
367
368
369
370
373
374
375
376
377
378
379
382
383
384
385
386
387
388
389
390
391
392
393
394
397
398
399
400
401
402
403
404
405
408
409
410
411
412
413
414
415
418
419
420
421
422
425
426
427
428
429
430
431
432
435
436
437
438
439
440
441
442
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
466
467
468
470#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
472
473
474
475
476
477
478
479
480
481
484
485
486
487
490
491
492
493
494
498
499
500
503
504
505
506
507
508
511
512
513
514
515
516
523 const QByteArrayData &d1 = a1.data_ptr();
524 const QByteArrayData &d2 = a2.data_ptr();
525 qsizetype n1 = d1.size;
526 qsizetype n2 = d2.size;
527 qsizetype n = qMax(n1, n2);
529 QByteArrayData bytes(n, n);
534 *bytes.ptr = *d1.ptr;
536 }
else if (n2 > n1) {
537 *bytes.ptr = *d2.ptr;
540 *bytes.ptr = qMin(*d1.ptr, *d2.ptr);
544 result.data_ptr() = std::move(bytes);
549QBitArray &performBitwiseOperationHelper(QBitArray &out,
const QBitArray &a1,
550 const QBitArray &a2, BitwiseOp op)
552 const QByteArrayData &d1 = a1.data_ptr();
553 const QByteArrayData &d2 = a2.data_ptr();
556 qsizetype n1 = d1.size;
557 qsizetype n2 = d2.size;
558 Q_ASSERT(out.data_ptr().size == qMax(n1, n2));
559 Q_ASSERT(out.data_ptr().size == 0 || !out.data_ptr().needsDetach());
563 auto dst =
reinterpret_cast<uchar *>(out.data_ptr().data());
564 auto p1 =
reinterpret_cast<
const uchar *>(d1.data());
565 auto p2 =
reinterpret_cast<
const uchar *>(d2.data());
572 for (qsizetype i = 1; i < n2; ++i)
573 dst[i] = op(p1[i], p2[i]);
578 for (qsizetype i = qMax(n2, qsizetype(1)); i < n1; ++i)
579 dst[i] = op(p1[i], uchar(0));
585QBitArray &performBitwiseOperationInCopy(QBitArray &self,
const QBitArray &other, BitwiseOp op)
587 QBitArray tmp(std::move(self));
588 self = sizedForOverwrite(tmp, other);
589 return performBitwiseOperationHelper(self, tmp, other, op);
593QBitArray &performBitwiseOperationInPlace(QBitArray &self,
const QBitArray &other, BitwiseOp op)
595 if (self.size() < other.size())
596 self.resize(other.size());
597 return performBitwiseOperationHelper(self, self, other, op);
603 if (self.data_ptr().needsDetach())
604 return performBitwiseOperationInCopy(self, other, op);
605 return performBitwiseOperationInPlace(self, other, op);
612 QByteArrayData &d1 = self.data_ptr();
613 QByteArrayData &d2 = other.data_ptr();
614 bool detached1 = !d1.needsDetach();
615 bool detached2 = !d2.needsDetach();
616 if (!detached1 && !detached2)
621 if (detached1 && detached2) {
623 swap = d1.allocatedCapacity() < d2.allocatedCapacity();
624 }
else if (detached2) {
636 auto choice = prepareForBitwiseOperation(self, other);
637 if (choice == InCopy)
638 return performBitwiseOperationInCopy(self, other, std::move(op));
639 return performBitwiseOperationInPlace(self, other, std::move(op));
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
660QBitArray &QBitArray::operator&=(QBitArray &&other)
662 return performBitwiseOperation(*
this, other, std::bit_and<uchar>());
665QBitArray &QBitArray::operator&=(
const QBitArray &other)
667 return performBitwiseOperation(*
this, other, std::bit_and<uchar>());
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
688QBitArray &QBitArray::operator|=(QBitArray &&other)
690 return performBitwiseOperation(*
this, other, std::bit_or<uchar>());
693QBitArray &QBitArray::operator|=(
const QBitArray &other)
695 return performBitwiseOperation(*
this, other, std::bit_or<uchar>());
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
716QBitArray &QBitArray::operator^=(QBitArray &&other)
718 return performBitwiseOperation(*
this, other, std::bit_xor<uchar>());
721QBitArray &QBitArray::operator^=(
const QBitArray &other)
723 return performBitwiseOperation(*
this, other, std::bit_xor<uchar>());
727
728
729
730
731
732
733
734
735
739 qsizetype n = d.size();
740 uchar *dst =
reinterpret_cast<uchar *>(data_ptr().data());
741 const uchar *src = dst;
742 QBitArray result([&] {
743 if (d.isDetached() || n == 0)
744 return std::move(d.data_ptr());
746 QByteArrayData tmp(n, n);
747 dst =
reinterpret_cast<uchar *>(tmp.data());
753 bitdiff = dst[0] = src[0];
755 for (qsizetype i = 1; i < n; ++i)
758 if (
int tailCount = 16 - bitdiff; tailCount != 8) {
761 uchar tailMask = (1U << tailCount) - 1;
762 dst[n - 1] &= tailMask;
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
789 QBitArray tmp = sizedForOverwrite(a1, a2);
790 performBitwiseOperationHelper(tmp, a1, a2, std::bit_and<uchar>());
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
815 QBitArray tmp = sizedForOverwrite(a1, a2);
816 performBitwiseOperationHelper(tmp, a1, a2, std::bit_or<uchar>());
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
841 QBitArray tmp = sizedForOverwrite(a1, a2);
842 performBitwiseOperationHelper(tmp, a1, a2, std::bit_xor<uchar>());
848
849
850
851
852
853
854
855
856
859
860
861
862
863
866
867
868
871
872
873
876
877
878
879
882
883
884
885
888
889
891#ifndef QT_NO_DATASTREAM
893
894
895
896
897
898
900QDataStream &operator<<(QDataStream &out,
const QBitArray &ba)
902 const qsizetype len = ba.size();
903 if (out.version() < QDataStream::Qt_6_0) {
904 if (Q_UNLIKELY(len > qsizetype{(std::numeric_limits<qint32>::max)()})) {
905 out.setStatus(QDataStream::Status::SizeLimitExceeded);
913 out.writeRawData(ba.d.data() + 1, ba.d.size() - 1);
918
919
920
921
922
923
925QDataStream &
operator>>(QDataStream &in, QBitArray &ba)
929 if (in.version() < QDataStream::Qt_6_0) {
932 if (Q_UNLIKELY(tmp > quint32((std::numeric_limits<qint32>::max)()))) {
933 in.setStatus(QDataStream::ReadCorruptData);
940 if (Q_UNLIKELY(tmp > quint64((std::numeric_limits<qsizetype>::max)()))) {
941 in.setStatus(QDataStream::Status::SizeLimitExceeded);
951 const qsizetype Step = 8 * 1024 * 1024;
952 const qsizetype totalBytes = storage_size(len);
953 qsizetype allocated = 0;
955 while (allocated < totalBytes) {
956 qsizetype blockSize = qMin(Step, totalBytes - allocated);
957 ba.d.resize(allocated + blockSize + 1);
958 if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
960 in.setStatus(QDataStream::ReadPastEnd);
963 allocated += blockSize;
966 const auto fromStream = ba.d.back();
967 adjust_head_and_tail(ba.d.data(), ba.d.size(), len);
968 if (ba.d.back() != fromStream) {
970 in.setStatus(QDataStream::ReadCorruptData);
977#ifndef QT_NO_DEBUG_STREAM
980 QDebugStateSaver saver(dbg);
981 dbg.nospace() <<
"QBitArray(";
982 for (qsizetype i = 0; i < array.size();) {
983 if (array.testBit(i))
988 if (!(i % 4) && (i < array.size()))
997
998
999
1002
1003
1004
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)
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)