summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qbitarray.h
blob: 4f99e693eb87cc12ef13e9c64cf71bcdd208f026 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QBITARRAY_H
#define QBITARRAY_H

#include <QtCore/qbytearray.h>

QT_BEGIN_NAMESPACE

class QBitRef;
class Q_CORE_EXPORT QBitArray
{
    Q_CORE_EXPORT friend QBitArray operator&(const QBitArray &a1, const QBitArray &a2);
    friend QBitArray operator&(QBitArray &&a1, const QBitArray &a2)
    { return a1 &= a2; }
    friend QBitArray operator&(const QBitArray &a1, QBitArray &&a2)
    { return a2 &= a1; }
    friend QBitArray operator&(QBitArray &&a1, QBitArray &&a2)
    { return a1 &= a2; }

    Q_CORE_EXPORT friend QBitArray operator|(const QBitArray &a1, const QBitArray &a2);
    friend QBitArray operator|(QBitArray &&a1, const QBitArray &a2)
    { return a1 |= a2; }
    friend QBitArray operator|(const QBitArray &a1, QBitArray &&a2)
    { return a2 |= a1; }
    friend QBitArray operator|(QBitArray &&a1, QBitArray &&a2)
    { return a1 |= a2; }

    Q_CORE_EXPORT friend QBitArray operator^(const QBitArray &a1, const QBitArray &a2);
    friend QBitArray operator^(QBitArray &&a1, const QBitArray &a2)
    { return a1 ^= a2; }
    friend QBitArray operator^(const QBitArray &a1, QBitArray &&a2)
    { return a2 ^= a1; }
    friend QBitArray operator^(QBitArray &&a1, QBitArray &&a2)
    { return a1 ^= a2; }

#ifndef QT_NO_DATASTREAM
    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
    friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
#endif
    friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept;
    friend QBitArray operator~(QBitArray a)
    { return std::move(a).inverted_inplace(); }
    QByteArray d;

    QBitArray(QByteArrayData &&dd) : d(std::move(dd)) {}

    template <typename BitArray> static auto bitLocation(BitArray &ba, qsizetype i)
    {
        Q_ASSERT(size_t(i) < size_t(ba.size()));
        struct R {
            decltype(ba.d[1]) byte;
            uchar bitMask;
        };
        qsizetype byteIdx = i >> 3;
        qsizetype bitIdx = i & 7;
        return R{ ba.d[1 + byteIdx], uchar(1U << bitIdx) };
    }

    QBitArray inverted_inplace() &&;

public:
    inline QBitArray() noexcept {}
    explicit QBitArray(qsizetype size, bool val = false);
    // Rule Of Zero applies
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
    QBitArray(const QBitArray &other) noexcept : d(other.d) {}
    inline QBitArray &operator=(const QBitArray &other) noexcept { d = other.d; return *this; }
    inline QBitArray(QBitArray &&other) noexcept : d(std::move(other.d)) {}
    QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBitArray)
#endif // Qt 6

    void swap(QBitArray &other) noexcept { d.swap(other.d); }

    qsizetype size() const { return qsizetype((size_t(d.size()) << 3) - *d.constData()); }
    qsizetype count() const { return size(); }
    qsizetype count(bool on) const;

    inline bool isEmpty() const { return d.isEmpty(); }
    inline bool isNull() const { return d.isNull(); }

    void resize(qsizetype size);

    inline void detach() { d.detach(); }
    inline bool isDetached() const { return d.isDetached(); }
    inline void clear() { d.clear(); }

    bool testBit(qsizetype i) const
    { auto r = bitLocation(*this, i); return r.byte & r.bitMask; }
    void setBit(qsizetype i)
    { auto r = bitLocation(*this, i); r.byte |= r.bitMask; }
    void setBit(qsizetype i, bool val)
    { if (val) setBit(i); else clearBit(i); }
    void clearBit(qsizetype i)
    { auto r = bitLocation(*this, i); r.byte &= ~r.bitMask; }
    bool toggleBit(qsizetype i)
    {
        auto r = bitLocation(*this, i);
        bool cl = r.byte & r.bitMask;
        r.byte ^= r.bitMask;
        return cl;
    }

    bool at(qsizetype i) const { return testBit(i); }
    inline QBitRef operator[](qsizetype i);
    bool operator[](qsizetype i) const { return testBit(i); }

    QBitArray &operator&=(QBitArray &&);
    QBitArray &operator|=(QBitArray &&);
    QBitArray &operator^=(QBitArray &&);
    QBitArray &operator&=(const QBitArray &);
    QBitArray &operator|=(const QBitArray &);
    QBitArray &operator^=(const QBitArray &);
#if QT_CORE_REMOVED_SINCE(6, 7)
    QBitArray operator~() const;
#endif

    inline bool operator==(const QBitArray &other) const { return d == other.d; }
    inline bool operator!=(const QBitArray &other) const { return d != other.d; }

    bool fill(bool aval, qsizetype asize = -1)
    { *this = QBitArray((asize < 0 ? this->size() : asize), aval); return true; }
    void fill(bool val, qsizetype first, qsizetype last);

    inline void truncate(qsizetype pos) { if (pos < size()) resize(pos); }

    const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; }
    static QBitArray fromBits(const char *data, qsizetype len);

    quint32 toUInt32(QSysInfo::Endian endianness, bool *ok = nullptr) const noexcept;

public:
    typedef QByteArray::DataPointer DataPtr;
    inline DataPtr &data_ptr() { return d.data_ptr(); }
    inline const DataPtr &data_ptr() const { return d.data_ptr(); }
};

class QT6_ONLY(Q_CORE_EXPORT) QBitRef
{
private:
    QBitArray &a;
    qsizetype i;
    inline QBitRef(QBitArray &array, qsizetype idx) : a(array), i(idx) { }
    friend class QBitArray;

public:
    inline operator bool() const { return a.testBit(i); }
    inline bool operator!() const { return !a.testBit(i); }
    QBitRef &operator=(const QBitRef &val) { a.setBit(i, val); return *this; }
    QBitRef &operator=(bool val) { a.setBit(i, val); return *this; }
};

QBitRef QBitArray::operator[](qsizetype i)
{ Q_ASSERT(i >= 0); return QBitRef(*this, i); }

#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
#endif

#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QBitArray &);
#endif

Q_DECLARE_SHARED(QBitArray)

QT_END_NAMESPACE

#endif // QBITARRAY_H