/* * Bitmap.h * * Created on: Jun 1, 2019 * Author: nathan */ #ifndef SRC_BITMAP_H_ #define SRC_BITMAP_H_ #include #include #include namespace qkernel { /** * Represents a fixed array of N bits. Somewhat analogous to std::bitset. Can * be manipulated using standard arithmetic operators (&, |, ^, ~). */ template class Bitmap { public: /** * A proxy object used to reference an individual bit contained in a Bitmap object. */ class Reference { public: /** * Construct a reference to a bit contained in a Bitmap object. * * @param data A reference to the byte in which the referenced bit is * contained * @param position The position of the referenced bit inside 'data.' 0 * denotes the least significant bit; 7 denoted the most significant * bit. */ Reference(uint8_t& data, size_t position); /** * Sets the bit referenced by this object to 'b' * * @returns a reference to this object */ Reference& operator=(const bool b); /** * Sets the bit referenced by this object to the value of the bit * referenced by 'r.' * * @returns a reference to this object */ Reference& operator=(const Reference& r); /** * @returns the inverse of the value of the bit referenced by this * object. */ bool operator~() const; /** * Converts the bit referenced by this object to a boolean, whose value * is 'true' if the bit referenced it set, and false if it is clear. */ operator bool() const; private: uint8_t& data; size_t position; }; /** * Constructs a bitmap containing 'N' bits, containing uninitialized * data. */ Bitmap(); /** * Constructs a bitmap containing 'N' bits, copying data from 'bitmap' into * the new object. */ Bitmap(const Bitmap& bitmap); /** * Constructs a bitmap containing 'N' bits, initializing each bit to 'v.' */ Bitmap(const bool value); /** * Constructs a bitmap containing 'N' bits, initializing the first 32 bits * to the bits contained in 'value.' If the bitmap contains more than 32 * bits, the rest are initialized to 0. */ Bitmap(const uint8_t value); /** * Constructs a bitmap containing 'N' bits, initializing the first 32 bits * to the bits contained in 'value.' If the bitmap contains more than 32 * bits, the rest are initialized to 0. */ Bitmap(const uint16_t value); /** * Constructs a bitmap containing 'N' bits, initializing the first 32 bits * to the bits contained in 'value.' If the bitmap contains more than 32 * bits, the rest are initialized to 0. */ Bitmap(const uint32_t value); /** * @returns the number of bits stored in this bitmap */ size_t size(); /** * @returns the number of bits that are set */ size_t count(); /** * @returns true if all bits are set; otherwise false. */ bool all(); /** * @returns true if at least one bit is set; otherwise false. */ bool any(); /** * @returns true if all bits are cleared; otherwise false. */ bool none(); /** * Sets all bits in this bitmap. * * @returns a reference to this bitmap */ Bitmap& set(); /** * Clears all bits in this bitmap. * * @returns a reference to this bitmap */ Bitmap& clear(); /** * Compares the contents of 'bitmap' and this bitmap. * * @param bitmap The bitmap to compare this object to. * * @returns true only if each bit in 'other' is equal to each bit in this * bitmap; otherwise false. */ bool operator==(const Bitmap& other) const; /** * Compares the contents of 'bitmap' and this bitmap. * * @param bitmap The bitmap to compare this object to. * * @returns false only if each bit in 'other' is equal to each bit in this * bitmap; otherwise true. */ bool operator!=(const Bitmap& other) const; /** * Accesses the bit at 'index.' Does not perform bounds checking; * out-of-bounds access will result in problems. * * @param index The position in the bitmap to access * * @returns a reference to the bit at 'index' */ Reference operator[](const size_t index); /** * Accesses the bit at 'index.' Does not perform bounds checking; * out-of-bounds access will result in problems. * * @param index The position in the bitmap to access * * @returns the value of the bit at position 'index' */ bool operator[](const size_t index) const; /** * @returns a bitmap containing the bitwise AND of this bitmap and 'other.' */ Bitmap operator&(const Bitmap& other) const; /** * Sets the value of this bitmap to the bitwise AND of this bitmap and * 'other.' * * @returns a reference to this bitmap */ Bitmap& operator&=(const Bitmap& other); /** * @returns a bitmap containing the bitwise OR of this bitmap and 'other.' */ Bitmap operator|(const Bitmap& other) const; /** * Sets the value of this bitmap to the bitwise OR of this bitmap and * 'other.' * * @returns a reference to this bitmap */ Bitmap& operator|=(const Bitmap& other); /** * @returns a bitmap containing the bitwise XOR of this bitmap and 'other.' */ Bitmap operator^(const Bitmap& other) const; /** * Sets the value of this bitmap to the bitwise OR of this bitmap and * 'other.' * * @returns a reference to this bitmap */ Bitmap& operator^=(const Bitmap& other); /** * Shifts this bitmap 'n' bits left. * * @returns a new Bitmap containing the result */ Bitmap operator<<(const size_t n) const; /** * Shifts this bitmap 'n' bits left. * * @returns a reference to this bitmap */ Bitmap& operator<<=(const size_t n); /** * Shifts this bitmap 'n' bits right. * * @returns a new Bitmap containing the result */ Bitmap operator>>(const size_t n) const; /** * Shifts the bitmap 'n' bits right. * * @returns a reference to this bitmap */ Bitmap& operator>>=(const size_t n); /** * Computes the bitwise NOT of this bitmap * * @returns a new bitmap containing the result */ Bitmap operator~() const; private: uint8_t data[(N / 8) + 1]; }; } /* namespace qkernel */ template inline qkernel::Bitmap::Reference::Reference(uint8_t& data, size_t position) : data(data) { this->position = position; } template inline typename qkernel::Bitmap::Reference& qkernel::Bitmap::Reference::operator =(const bool b) { if(b) { data |= 1 << position; } else { data &= ~(1 << position); } return *this; } template inline typename qkernel::Bitmap::Reference& qkernel::Bitmap::Reference::operator =(const Reference& r) { if((bool) r) { data |= 1 << position; } else { data &= ~(1 << position); } } template inline bool qkernel::Bitmap::Reference::operator ~() const { return !((bool) (*this)); } template inline qkernel::Bitmap::Reference::operator bool() const { uint8_t value = data & (1 << position); if((data & (1 << position)) != 0) { return true; } else { return false; } } template inline qkernel::Bitmap::Bitmap() { } template inline qkernel::Bitmap::Bitmap(const Bitmap& bitmap) { for(size_t i = 0; i < N; i++) { (*this)[i] = bitmap[i]; } } template inline qkernel::Bitmap::Bitmap(const bool value) { for(size_t i = 0; i < N; i++) { (*this)[i] = value; } } template inline qkernel::Bitmap::Bitmap(uint8_t value) { size_t max = N >= 8 ? 8 : N; for(size_t i = 0; i < max; i++) { (*this)[i] = value & 1; value >>= 1; } } template inline qkernel::Bitmap::Bitmap(uint16_t value) { size_t max = N >= 16 ? 16 : N; for(size_t i = 0; i < max; i++) { (*this)[i] = value & 1; value >>= 1; } } template inline qkernel::Bitmap::Bitmap(uint32_t value) { size_t max = N >= 32 ? 32 : N; for(size_t i = 0; i < max; i++) { (*this)[i] = value & 1; value >>= 1; } } template inline size_t qkernel::Bitmap::size() { return N; } template inline size_t qkernel::Bitmap::count() { size_t count = 0; for(size_t i = 0; i < N; i++) { if((*this)[i] == true) { count++; } } return count; } template inline bool qkernel::Bitmap::all() { for(size_t i = 0; i < N; i++) { if((*this)[i] == false) { return false; } } return true; } template inline bool qkernel::Bitmap::any() { for(size_t i = 0; i < N; i++) { if((*this)[i] == true) { return true; } } return false; } template inline bool qkernel::Bitmap::none() { for(size_t i = 0; i < N; i++) { if((*this)[i] == true) { return false; } } return true; } template inline qkernel::Bitmap& qkernel::Bitmap::set() { for(size_t i = 0; i < N; i++) { (*this)[i] = true; } return *this; } template inline qkernel::Bitmap& qkernel::Bitmap::clear() { for(size_t i = 0; i < N; i++) { (*this)[i] = false; } return *this; } template inline bool qkernel::Bitmap::operator ==(const Bitmap& other) const { for(size_t i = 0; i < N; i++) { if((*this)[i] != other[i]) { return false; } } return true; } template inline bool qkernel::Bitmap::operator !=(const Bitmap& other) const { return !((*this) == other); } template inline typename qkernel::Bitmap::Reference qkernel::Bitmap::operator [](const size_t index) { return Reference(data[index / 8], index % 8); } template inline bool qkernel::Bitmap::operator [](const size_t index) const { return (data[index/8] & (1 << (index % 8))) == 0 ? false : true; } template inline qkernel::Bitmap qkernel::Bitmap::operator &(const Bitmap& other) const { Bitmap result; for(size_t i = 0; i < N; i++) { result[i] = (*this)[i] && other[i]; } return result; } template inline qkernel::Bitmap& qkernel::Bitmap::operator &=(const Bitmap& other) { for(size_t i = 0; i < N; i++) { (*this)[i] = (*this)[i] && other[i]; } return *this; } template inline qkernel::Bitmap qkernel::Bitmap::operator |(const Bitmap& other) const { Bitmap result; for(size_t i = 0; i < N; i++) { result[i] = (*this)[i] || other[i]; } return result; } template inline qkernel::Bitmap& qkernel::Bitmap::operator |=(const Bitmap& other) { for(size_t i = 0; i < N; i++) { (*this)[i] = (*this)[i] || other[i]; } return *this; } template inline qkernel::Bitmap qkernel::Bitmap::operator ^(const Bitmap& other) const { Bitmap result; for(size_t i = 0; i < N; i++) { result[i] = (*this)[i] ^ other[i]; } return result; } template inline qkernel::Bitmap& qkernel::Bitmap::operator ^=(const Bitmap& other) { for(size_t i = 0; i < N; i++) { (*this)[i] = (*this)[i] ^ other[i]; } return *this; } template inline qkernel::Bitmap qkernel::Bitmap::operator <<(const size_t n) const { Bitmap result; for(size_t i = 0; i < N; i++) { if(i < n) { result[i] = false; } else { result[i] = (*this)[i-n]; } } return result; } template inline qkernel::Bitmap& qkernel::Bitmap::operator <<=(const size_t n) { for(size_t i = 0; i < N; i++) { if(i == 0) { (*this)[i] = 0; } else { (*this)[i] = (*this)[i-1]; } } return *this; } template inline qkernel::Bitmap qkernel::Bitmap::operator >>(const size_t n) const { Bitmap result; for(size_t i = 0; i < N; i++) { if(i > N - n) { result[i] = false; } else { result[i] = (*this)[i+n]; } } return result; } template inline qkernel::Bitmap& qkernel::Bitmap::operator >>=(const size_t n) { for(size_t i = N - 1; i >= 0; i--) { if(i == N - 1) { (*this)[i] = 0; } else { (*this)[i] = (*this)[i+1]; } } return *this; } template inline qkernel::Bitmap qkernel::Bitmap::operator ~() const { Bitmap result; for(size_t i = 0; i < N; i++) { result[i] = !(*this)[i]; } return result; } #endif /* SRC_BITMAP_H_ */