| 1 | // Licensed to the .NET Foundation under one or more agreements. | 
|---|
| 2 | // The .NET Foundation licenses this file to you under the MIT license. | 
|---|
| 3 | // See the LICENSE file in the project root for more information. | 
|---|
| 4 |  | 
|---|
| 5 | #ifndef TINYARRAY_H | 
|---|
| 6 | #define TINYARRAY_H | 
|---|
| 7 |  | 
|---|
| 8 | /*****************************************************************************/ | 
|---|
| 9 |  | 
|---|
| 10 | // This is an array packed into some kind of integral data type | 
|---|
| 11 | // storagetype is the type (integral) which your array is going to be packed into | 
|---|
| 12 | // itemtype is the type of array elements | 
|---|
| 13 | // bits_per_element is size of the elements in bits | 
|---|
| 14 | template <class storageType, class itemType, int bits_per_element> | 
|---|
| 15 | class TinyArray | 
|---|
| 16 | { | 
|---|
| 17 | public: | 
|---|
| 18 | // operator[] returns a 'ref' (usually a ref to the element type) | 
|---|
| 19 | // This presents a problem if you wanted to implement something like a | 
|---|
| 20 | // bitvector via this packed array, because you cannot make a ref to | 
|---|
| 21 | // the element type. | 
|---|
| 22 | //    The trick is you define something that acts like a ref (TinyArrayRef in this case) | 
|---|
| 23 | // which for our purposes means you can assign to and from it and our chosen | 
|---|
| 24 | // element type. | 
|---|
| 25 | class TinyArrayRef | 
|---|
| 26 | { | 
|---|
| 27 | public: | 
|---|
| 28 | // this is really the getter for the array. | 
|---|
| 29 | operator itemType() | 
|---|
| 30 | { | 
|---|
| 31 | storageType mask  = ((1 << bits_per_element) - 1); | 
|---|
| 32 | int         shift = bits_per_element * index; | 
|---|
| 33 |  | 
|---|
| 34 | itemType result = (itemType)((*data >> shift) & mask); | 
|---|
| 35 | return result; | 
|---|
| 36 | } | 
|---|
| 37 |  | 
|---|
| 38 | void operator=(const itemType b) | 
|---|
| 39 | { | 
|---|
| 40 | storageType mask = ((1 << bits_per_element) - 1); | 
|---|
| 41 | assert(itemType(b & mask) == b); | 
|---|
| 42 |  | 
|---|
| 43 | mask <<= bits_per_element * index; | 
|---|
| 44 |  | 
|---|
| 45 | *data &= ~mask; | 
|---|
| 46 | *data |= b << (bits_per_element * index); | 
|---|
| 47 | } | 
|---|
| 48 | friend class TinyArray; | 
|---|
| 49 |  | 
|---|
| 50 | protected: | 
|---|
| 51 | TinyArrayRef(storageType* d, int idx) : data(d), index(idx) | 
|---|
| 52 | { | 
|---|
| 53 | } | 
|---|
| 54 |  | 
|---|
| 55 | storageType* data; | 
|---|
| 56 | int          index; | 
|---|
| 57 | }; | 
|---|
| 58 |  | 
|---|
| 59 | storageType data; | 
|---|
| 60 |  | 
|---|
| 61 | void clear() | 
|---|
| 62 | { | 
|---|
| 63 | data = 0; | 
|---|
| 64 | } | 
|---|
| 65 |  | 
|---|
| 66 | TinyArrayRef operator[](unsigned int n) | 
|---|
| 67 | { | 
|---|
| 68 | assert((n + 1) * bits_per_element <= sizeof(itemType) * 8); | 
|---|
| 69 | return TinyArrayRef(&data, n); | 
|---|
| 70 | } | 
|---|
| 71 | // only use this for clearing it | 
|---|
| 72 | void operator=(void* rhs) | 
|---|
| 73 | { | 
|---|
| 74 | assert(rhs == nullptr); | 
|---|
| 75 | data = 0; | 
|---|
| 76 | } | 
|---|
| 77 | }; | 
|---|
| 78 |  | 
|---|
| 79 | #endif // TINYARRAY_H | 
|---|
| 80 |  | 
|---|