7#include <qalgorithms.h>
8#include <qdatastream.h>
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
81
83#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
85
86
87
88
89
90
91
95
96
97
98
99
102
103
104
105
106
107
108
109
110
111
112
113
118 return qsizetype((size_t(size) + 7) / 8);
123 return size <= 0 ? 0 : storage_size(size) + 1;
128 quint8 *c =
reinterpret_cast<quint8 *>(data);
130 *c = quint8(size_t(storageSize) * 8 - logicalSize);
133 *(c + 1 + logicalSize / 8) &= (1 << (logicalSize & 7)) - 1;
137
138
139
140QBitArray::QBitArray(qsizetype size,
bool value)
141 : d(allocation_size(size), value ? 0xFF : 0x00)
143 Q_ASSERT_X(size >= 0,
"QBitArray::QBitArray",
"Size must be greater than or equal to 0.");
147 adjust_head_and_tail(d.data(), d.size(), size);
151
152
153
154
155
158
159
160
163
164
165
166
167qsizetype QBitArray::count(
bool on)
const
169 qsizetype numBits = 0;
170 const quint8 *bits =
reinterpret_cast<
const quint8 *>(d.data()) + 1;
174 const quint8 *
const end =
reinterpret_cast<
const quint8 *>(d.end());
176 while (bits + 7 <= end) {
177 quint64 v = qFromUnaligned<quint64>(bits);
179 numBits += qsizetype(qPopulationCount(v));
181 if (bits + 3 <= end) {
182 quint32 v = qFromUnaligned<quint32>(bits);
184 numBits += qsizetype(qPopulationCount(v));
186 if (bits + 1 < end) {
187 quint16 v = qFromUnaligned<quint16>(bits);
189 numBits += qsizetype(qPopulationCount(v));
192 numBits += qsizetype(qPopulationCount(bits[0]));
194 return on ? numBits : size() - numBits;
198
199
200
201
202
203
204
205
206
207
208
209void QBitArray::resize(qsizetype size)
211 Q_ASSERT_X(size >= 0,
"QBitArray::resize",
"Size must be greater than or equal to 0.");
215 d.resize(allocation_size(size), 0x00);
216 adjust_head_and_tail(d.data(), d.size(), size);
221
222
223
224
225
226
229
230
231
232
233
234
235
236
237
238
239
240
241
244
245
246
247
248
249
250
251
252
253
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
272void QBitArray::fill(
bool value, qsizetype begin, qsizetype end)
274 while (begin < end && begin & 0x7)
275 setBit(begin++, value);
276 qsizetype len = end - begin;
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);
284 setBit(begin++, value);
288
289
290
291
292
293
294
295
296
299
300
301
302
303
304
305
306
307
308
309
310QBitArray QBitArray::fromBits(
const char *data, qsizetype size)
312 Q_ASSERT_X(size >= 0,
"QBitArray::fromBits",
"Size must be greater than or equal to 0.");
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);
325
326
327
328
329
330
331
332
333quint32 QBitArray::toUInt32(QSysInfo::Endian endianness,
bool *ok)
const noexcept
335 const qsizetype _size = size();
347 for (qsizetype i = 0; i < _size; ++i, factor *= 2) {
348 const auto index = endianness == QSysInfo::Endian::LittleEndian ? i : (_size - i - 1);
357
358
359
362
363
364
367
368
369
370
371
374
375
376
377
378
379
380
383
384
385
386
387
388
389
390
391
392
393
394
395
398
399
400
401
402
403
404
405
406
409
410
411
412
413
414
415
416
419
420
421
422
423
426
427
428
429
430
431
432
433
436
437
438
439
440
441
442
443
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
467
468
469
471#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
473
474
475
476
477
478
479
480
481
482
485
486
487
488
491
492
493
494
495
499
500
501
504
505
506
507
508
509
512
513
514
515
516
517
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);
530 QByteArrayData bytes(n, n);
535 *bytes.ptr = *d1.ptr;
537 }
else if (n2 > n1) {
538 *bytes.ptr = *d2.ptr;
541 *bytes.ptr = qMin(*d1.ptr, *d2.ptr);
545 result.data_ptr() = std::move(bytes);
550QBitArray &performBitwiseOperationHelper(QBitArray &out,
const QBitArray &a1,
551 const QBitArray &a2, BitwiseOp op)
553 const QByteArrayData &d1 = a1.data_ptr();
554 const QByteArrayData &d2 = a2.data_ptr();
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());
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());
573 for (qsizetype i = 1; i < n2; ++i)
574 dst[i] = op(p1[i], p2[i]);
579 for (qsizetype i = qMax(n2, qsizetype(1)); i < n1; ++i)
580 dst[i] = op(p1[i], uchar(0));
586QBitArray &performBitwiseOperationInCopy(QBitArray &self,
const QBitArray &other, BitwiseOp op)
588 QBitArray tmp(std::move(self));
589 self = sizedForOverwrite(tmp, other);
590 return performBitwiseOperationHelper(self, tmp, other, op);
594QBitArray &performBitwiseOperationInPlace(QBitArray &self,
const QBitArray &other, BitwiseOp op)
596 if (self.size() < other.size())
597 self.resize(other.size());
598 return performBitwiseOperationHelper(self, self, other, op);
604 if (self.data_ptr().needsDetach())
605 return performBitwiseOperationInCopy(self, other, op);
606 return performBitwiseOperationInPlace(self, other, op);
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)
622 if (detached1 && detached2) {
624 swap = d1.allocatedCapacity() < d2.allocatedCapacity();
625 }
else if (detached2) {
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));
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
661QBitArray &QBitArray::operator&=(QBitArray &&other)
663 return performBitwiseOperation(*
this, other, std::bit_and<uchar>());
666QBitArray &QBitArray::operator&=(
const QBitArray &other)
668 return performBitwiseOperation(*
this, other, std::bit_and<uchar>());
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
689QBitArray &QBitArray::operator|=(QBitArray &&other)
691 return performBitwiseOperation(*
this, other, std::bit_or<uchar>());
694QBitArray &QBitArray::operator|=(
const QBitArray &other)
696 return performBitwiseOperation(*
this, other, std::bit_or<uchar>());
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
717QBitArray &QBitArray::operator^=(QBitArray &&other)
719 return performBitwiseOperation(*
this, other, std::bit_xor<uchar>());
722QBitArray &QBitArray::operator^=(
const QBitArray &other)
724 return performBitwiseOperation(*
this, other, std::bit_xor<uchar>());
728
729
730
731
732
733
734
735
736
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());
747 QByteArrayData tmp(n, n);
748 dst =
reinterpret_cast<uchar *>(tmp.data());
754 bitdiff = dst[0] = src[0];
756 for (qsizetype i = 1; i < n; ++i)
759 if (
int tailCount = 16 - bitdiff; tailCount != 8) {
762 uchar tailMask = (1U << tailCount) - 1;
763 dst[n - 1] &= tailMask;
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
790 QBitArray tmp = sizedForOverwrite(a1, a2);
791 performBitwiseOperationHelper(tmp, a1, a2, std::bit_and<uchar>());
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
816 QBitArray tmp = sizedForOverwrite(a1, a2);
817 performBitwiseOperationHelper(tmp, a1, a2, std::bit_or<uchar>());
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
842 QBitArray tmp = sizedForOverwrite(a1, a2);
843 performBitwiseOperationHelper(tmp, a1, a2, std::bit_xor<uchar>());
849
850
851
852
853
854
855
856
857
860
861
862
863
864
867
868
869
872
873
874
877
878
879
880
883
884
885
886
889
890
892#ifndef QT_NO_DATASTREAM
894
895
896
897
898
899
901QDataStream &operator<<(QDataStream &out,
const QBitArray &ba)
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);
914 out.writeRawData(ba.d.data() + 1, ba.d.size() - 1);
919
920
921
922
923
924
926QDataStream &
operator>>(QDataStream &in, QBitArray &ba)
930 if (in.version() < QDataStream::Qt_6_0) {
933 if (Q_UNLIKELY(tmp > quint32((std::numeric_limits<qint32>::max)()))) {
934 in.setStatus(QDataStream::ReadCorruptData);
941 if (Q_UNLIKELY(tmp > quint64((std::numeric_limits<qsizetype>::max)()))) {
942 in.setStatus(QDataStream::Status::SizeLimitExceeded);
952 const qsizetype Step = 8 * 1024 * 1024;
953 const qsizetype totalBytes = storage_size(len);
954 qsizetype allocated = 0;
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) {
961 in.setStatus(QDataStream::ReadPastEnd);
964 allocated += blockSize;
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) {
971 in.setStatus(QDataStream::ReadCorruptData);
978#ifndef QT_NO_DEBUG_STREAM
981 QDebugStateSaver saver(dbg);
982 dbg.nospace() <<
"QBitArray(";
983 for (qsizetype i = 0; i < array.size();) {
984 if (array.testBit(i))
989 if (!(i % 4) && (i < array.size()))
998
999
1000
1003
1004
1005
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)