summaryrefslogtreecommitdiff
path: root/src/jit/tinyarray.h
blob: bee59bdb594ebf28bb4acc83e887f500dca88bc1 (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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#ifndef TINYARRAY_H
#define TINYARRAY_H

/*****************************************************************************/

// This is an array packed into some kind of integral data type
// storagetype is the type (integral) which your array is going to be packed into
// itemtype is the type of array elements
// bits_per_element is size of the elements in bits
template <class storageType, class itemType, int bits_per_element>
class TinyArray
{
public:
    // operator[] returns a 'ref' (usually a ref to the element type)
    // This presents a problem if you wanted to implement something like a
    // bitvector via this packed array, because you cannot make a ref to
    // the element type.
    //    The trick is you define something that acts like a ref (TinyArrayRef in this case)
    // which for our purposes means you can assign to and from it and our chosen
    // element type.
    class TinyArrayRef
    {
    public:
        // this is really the getter for the array.
        operator itemType()
        {
            storageType mask  = ((1 << bits_per_element) - 1);
            int         shift = bits_per_element * index;

            itemType result = (itemType)((*data >> shift) & mask);
            return result;
        }

        void operator=(const itemType b)
        {
            storageType mask = ((1 << bits_per_element) - 1);
            assert(itemType(b & mask) == b);

            mask <<= bits_per_element * index;

            *data &= ~mask;
            *data |= b << (bits_per_element * index);
        }
        friend class TinyArray;

    protected:
        TinyArrayRef(storageType* d, int idx) : data(d), index(idx)
        {
        }

        storageType* data;
        int          index;
    };

    storageType data;

    void clear()
    {
        data = 0;
    }

    TinyArrayRef operator[](unsigned int n)
    {
        assert((n + 1) * bits_per_element <= sizeof(itemType) * 8);
        return TinyArrayRef(&data, n);
    }
    // only use this for clearing it
    void operator=(void* rhs)
    {
        assert(rhs == nullptr);
        data = 0;
    }
};

#endif // TINYARRAY_H