Line data Source code
1 : /* ✔ */ 2 : 3 : #pragma once 4 : 5 : #include <AH/Settings/Warnings.hpp> 6 : 7 : AH_DIAGNOSTIC_WERROR() // Enable errors on warnings 8 : 9 : #include <AH/Error/Error.hpp> 10 : #include <AH/Settings/NamespaceSettings.hpp> 11 : #include <stdint.h> 12 : 13 : /// @addtogroup AH_Containers 14 : /// @{ 15 : 16 : BEGIN_AH_NAMESPACE 17 : 18 : /** 19 : * @brief A class for arrays of bits. 20 : * 21 : * @tparam N 22 : * The number of bits. 23 : */ 24 : template <uint8_t N> 25 6 : class BitArray { 26 : public: 27 : /** 28 : * @brief Get the value of the given bit. 29 : * 30 : * @param bitIndex 31 : * The (zero-based) index of the bit to read. 32 : */ 33 65 : bool get(uint8_t bitIndex) { 34 65 : return buffer[getBufferIndex(bitIndex)] & getBufferMask(bitIndex); 35 : } 36 : 37 : /** 38 : * @brief Set the value of the given bit to 1. 39 : * 40 : * @param bitIndex 41 : * The (zero-based) index of the bit to set. 42 : */ 43 3 : void set(uint8_t bitIndex) { 44 3 : buffer[getBufferIndex(bitIndex)] |= getBufferMask(bitIndex); 45 3 : } 46 : 47 : /** 48 : * @brief Clear the value of the given bit to 0. 49 : * 50 : * @param bitIndex 51 : * The (zero-based) index of the bit to clear. 52 : */ 53 2 : void clear(uint8_t bitIndex) { 54 2 : buffer[getBufferIndex(bitIndex)] &= ~getBufferMask(bitIndex); 55 2 : } 56 : 57 : /** 58 : * @brief Set the value of the given bit to the given state. 59 : * 60 : * @param bitIndex 61 : * The (zero-based) index of the bit to set. 62 : * @param state 63 : * The value to set the bit to. 64 : */ 65 2 : void set(uint8_t bitIndex, bool state) { 66 2 : state ? set(bitIndex) : clear(bitIndex); 67 2 : } 68 : 69 : /** 70 : * @brief Check the given byte index, and return it if it is within the 71 : * bounds of the array, otherwise, throw an error, and return 72 : * the last valid index. 73 : * 74 : * @param byteIndex 75 : * The index to check. 76 : */ 77 70 : uint8_t safeIndex(uint8_t byteIndex) const { 78 70 : if (byteIndex >= getBufferLength()) { 79 1 : ERROR(F("Error: index out of bounds (") 80 : << byteIndex << F(", length is ") << getBufferLength() 81 : << ')', 82 : 0xFFFF); 83 0 : return getBufferLength() - 1; 84 : } 85 69 : return byteIndex; 86 70 : } 87 : 88 : /** 89 : * @brief Get the byte at the given index. 90 : * 91 : * This function can be used to quickly access all of the bits, to send 92 : * them out to a shift register, for example. 93 : * 94 : * @note No bounds checking is performed. 95 : * 96 : * @param byteIndex 97 : * The index of the byte within the array. 98 : */ 99 : uint8_t getByte(uint8_t byteIndex) const { 100 : return buffer[byteIndex]; 101 : // return buffer[safeIndex(byteIndex)]; 102 : } 103 : 104 : /** 105 : * @brief Get the buffer length in bytes. 106 : */ 107 71 : uint8_t getBufferLength() const { return bufferLength; } 108 : 109 : private: 110 70 : uint8_t getBufferIndex(uint8_t bitIndex) const { 111 70 : return safeIndex(bitIndex / 8); 112 : } 113 69 : uint8_t getBufferBit(uint8_t bitIndex) const { return bitIndex % 8; } 114 69 : uint8_t getBufferMask(uint8_t bitIndex) const { 115 69 : return 1 << getBufferBit(bitIndex); 116 : } 117 : 118 : constexpr static uint8_t bufferLength = (uint8_t)((N + 7) / 8); 119 6 : uint8_t buffer[bufferLength] = {}; 120 : }; 121 : 122 : END_AH_NAMESPACE 123 : 124 : /// @} 125 : 126 : AH_DIAGNOSTIC_POP()