1 | // Copyright (C) 2020 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QBITARRAY_H |
5 | #define QBITARRAY_H |
6 | |
7 | #include <QtCore/qbytearray.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | class QBitRef; |
12 | class Q_CORE_EXPORT QBitArray |
13 | { |
14 | #ifndef QT_NO_DATASTREAM |
15 | friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &); |
16 | friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &); |
17 | #endif |
18 | friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept; |
19 | QByteArray d; |
20 | |
21 | public: |
22 | inline QBitArray() noexcept {} |
23 | explicit QBitArray(qsizetype size, bool val = false); |
24 | QBitArray(const QBitArray &other) noexcept : d(other.d) {} |
25 | inline QBitArray &operator=(const QBitArray &other) noexcept { d = other.d; return *this; } |
26 | inline QBitArray(QBitArray &&other) noexcept : d(std::move(other.d)) {} |
27 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBitArray) |
28 | |
29 | void swap(QBitArray &other) noexcept { d.swap(other&: other.d); } |
30 | |
31 | inline qsizetype size() const { return (d.size() << 3) - *d.constData(); } |
32 | inline qsizetype count() const { return (d.size() << 3) - *d.constData(); } |
33 | qsizetype count(bool on) const; |
34 | |
35 | inline bool isEmpty() const { return d.isEmpty(); } |
36 | inline bool isNull() const { return d.isNull(); } |
37 | |
38 | void resize(qsizetype size); |
39 | |
40 | inline void detach() { d.detach(); } |
41 | inline bool isDetached() const { return d.isDetached(); } |
42 | inline void clear() { d.clear(); } |
43 | |
44 | bool testBit(qsizetype i) const; |
45 | void setBit(qsizetype i); |
46 | void setBit(qsizetype i, bool val); |
47 | void clearBit(qsizetype i); |
48 | bool toggleBit(qsizetype i); |
49 | |
50 | bool at(qsizetype i) const; |
51 | QBitRef operator[](qsizetype i); |
52 | bool operator[](qsizetype i) const; |
53 | |
54 | QBitArray &operator&=(const QBitArray &); |
55 | QBitArray &operator|=(const QBitArray &); |
56 | QBitArray &operator^=(const QBitArray &); |
57 | QBitArray operator~() const; |
58 | |
59 | inline bool operator==(const QBitArray &other) const { return d == other.d; } |
60 | inline bool operator!=(const QBitArray &other) const { return d != other.d; } |
61 | |
62 | inline bool fill(bool val, qsizetype size = -1); |
63 | void fill(bool val, qsizetype first, qsizetype last); |
64 | |
65 | inline void truncate(qsizetype pos) { if (pos < size()) resize(size: pos); } |
66 | |
67 | const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; } |
68 | static QBitArray fromBits(const char *data, qsizetype len); |
69 | |
70 | quint32 toUInt32(QSysInfo::Endian endianness, bool *ok = nullptr) const noexcept; |
71 | |
72 | public: |
73 | typedef QByteArray::DataPointer DataPtr; |
74 | inline DataPtr &data_ptr() { return d.data_ptr(); } |
75 | }; |
76 | |
77 | inline bool QBitArray::fill(bool aval, qsizetype asize) |
78 | { *this = QBitArray((asize < 0 ? this->size() : asize), aval); return true; } |
79 | |
80 | Q_CORE_EXPORT QBitArray operator&(const QBitArray &, const QBitArray &); |
81 | Q_CORE_EXPORT QBitArray operator|(const QBitArray &, const QBitArray &); |
82 | Q_CORE_EXPORT QBitArray operator^(const QBitArray &, const QBitArray &); |
83 | |
84 | inline bool QBitArray::testBit(qsizetype i) const |
85 | { Q_ASSERT(size_t(i) < size_t(size())); |
86 | return (*(reinterpret_cast<const uchar*>(d.constData())+1+(i>>3)) & (1 << (i & 7))) != 0; } |
87 | |
88 | inline void QBitArray::setBit(qsizetype i) |
89 | { Q_ASSERT(size_t(i) < size_t(size())); |
90 | *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) |= uchar(1 << (i & 7)); } |
91 | |
92 | inline void QBitArray::clearBit(qsizetype i) |
93 | { Q_ASSERT(size_t(i) < size_t(size())); |
94 | *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) &= ~uchar(1 << (i & 7)); } |
95 | |
96 | inline void QBitArray::setBit(qsizetype i, bool val) |
97 | { if (val) setBit(i); else clearBit(i); } |
98 | |
99 | inline bool QBitArray::toggleBit(qsizetype i) |
100 | { Q_ASSERT(size_t(i) < size_t(size())); |
101 | uchar b = uchar(1<<(i&7)); uchar* p = reinterpret_cast<uchar*>(d.data())+1+(i>>3); |
102 | uchar c = uchar(*p&b); *p^=b; return c!=0; } |
103 | |
104 | inline bool QBitArray::operator[](qsizetype i) const { return testBit(i); } |
105 | inline bool QBitArray::at(qsizetype i) const { return testBit(i); } |
106 | |
107 | class Q_CORE_EXPORT QBitRef |
108 | { |
109 | private: |
110 | QBitArray &a; |
111 | qsizetype i; |
112 | inline QBitRef(QBitArray &array, qsizetype idx) : a(array), i(idx) { } |
113 | friend class QBitArray; |
114 | |
115 | public: |
116 | inline operator bool() const { return a.testBit(i); } |
117 | inline bool operator!() const { return !a.testBit(i); } |
118 | QBitRef &operator=(const QBitRef &val) { a.setBit(i, val); return *this; } |
119 | QBitRef &operator=(bool val) { a.setBit(i, val); return *this; } |
120 | }; |
121 | |
122 | inline QBitRef QBitArray::operator[](qsizetype i) |
123 | { Q_ASSERT(i >= 0); return QBitRef(*this, i); } |
124 | |
125 | #ifndef QT_NO_DATASTREAM |
126 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &); |
127 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &); |
128 | #endif |
129 | |
130 | #ifndef QT_NO_DEBUG_STREAM |
131 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QBitArray &); |
132 | #endif |
133 | |
134 | Q_DECLARE_SHARED(QBitArray) |
135 | |
136 | QT_END_NAMESPACE |
137 | |
138 | #endif // QBITARRAY_H |
139 | |