summaryrefslogtreecommitdiff
path: root/include/util/bitset.hpp
blob: 8798a4ab2fd05ee3aedc459d936819bb40fa28fe (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
#pragma once

#include <array>
#include <cassert>
#include <cstdint>

constexpr int bits_ceil(int bits) {
    return bits / 8 + (bits % 8 > 0 ? 1 : 0);
}

template <unsigned int flags, auto size = bits_ceil(flags)>
struct bitset : std::array<std::uint8_t, size> {
    using array_type = std::array<std::uint8_t, size>;

private:
    struct bit_ref {
        bitset<flags> &a;
        int     referenced_byte;
        uint8_t referenced_bit_mask;
        
        bool operator=(bool b) {
            if (b)
                a.at(referenced_byte) |= referenced_bit_mask;
            else 
                a.at(referenced_byte) &= ~referenced_bit_mask;
            return b;        
        }

        constexpr operator bool() const {
            return (a.at(referenced_byte) & referenced_bit_mask) > 0;
        }
    };

public:
    template<class T>
    constexpr bool operator [](T idx) const {
        unsigned int i = (unsigned int)(idx);
        assert(i < flags);
        return (array_type::at(i/8) & (1 << (i%8))) > 0;
    }

    template<class T>
    bit_ref operator[](T idx)  {
        unsigned int i = (unsigned int)(idx);
        assert(i < flags);
        return bit_ref(*this, i/8, (1 << (i%8)));
    }
};