File indexing completed on 2024-06-02 05:05:36
0001 /* 0002 SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "bitset.h" 0007 #include <algorithm> 0008 #include <string.h> 0009 0010 namespace bt 0011 { 0012 BitSet BitSet::null; 0013 0014 BitSet::BitSet(Uint32 num_bits) 0015 : num_bits(num_bits) 0016 , data(nullptr) 0017 { 0018 num_bytes = (num_bits >> 3) + (((num_bits & 7) > 0) ? 1 : 0); 0019 data = new Uint8[num_bytes]; 0020 std::fill(data, data + num_bytes, 0x00); 0021 num_on = 0; 0022 } 0023 0024 BitSet::BitSet(const Uint8 *d, Uint32 num_bits) 0025 : num_bits(num_bits) 0026 , data(nullptr) 0027 { 0028 num_bytes = (num_bits >> 3) + (((num_bits & 7) > 0) ? 1 : 0); 0029 data = new Uint8[num_bytes]; 0030 memcpy(data, d, num_bytes); 0031 num_on = 0; 0032 updateNumOnBits(); 0033 } 0034 0035 BitSet::BitSet(const BitSet &bs) 0036 : num_bits(bs.num_bits) 0037 , num_bytes(bs.num_bytes) 0038 , data(nullptr) 0039 , num_on(bs.num_on) 0040 { 0041 data = new Uint8[num_bytes]; 0042 std::copy(bs.data, bs.data + num_bytes, data); 0043 } 0044 0045 BitSet::~BitSet() 0046 { 0047 delete[] data; 0048 } 0049 0050 void BitSet::updateNumOnBits() 0051 { 0052 num_on = 0; 0053 Uint32 i = 0; 0054 while (i < num_bytes) { 0055 num_on += BitCount[data[i]]; 0056 i++; 0057 } 0058 } 0059 0060 BitSet &BitSet::operator=(const BitSet &bs) 0061 { 0062 delete[] data; 0063 num_bytes = bs.num_bytes; 0064 num_bits = bs.num_bits; 0065 data = new Uint8[num_bytes]; 0066 std::copy(bs.data, bs.data + num_bytes, data); 0067 num_on = bs.num_on; 0068 return *this; 0069 } 0070 0071 const Uint8 tail_mask_lookup[8] = {0xFF, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F}; 0072 0073 void BitSet::invert() 0074 { 0075 if (num_bytes <= 0) 0076 return; 0077 0078 num_on = 0; 0079 Uint32 i = 0; 0080 while (i < num_bytes - 1) { 0081 data[i] = ~data[i]; 0082 num_on += BitCount[data[i]]; 0083 i++; 0084 } 0085 // i == num_bytes-1 0086 data[i] = ~data[i] & tail_mask_lookup[num_bits & 7]; 0087 num_on += BitCount[data[i]]; 0088 } 0089 0090 BitSet &BitSet::operator-=(const BitSet &bs) 0091 { 0092 num_on = 0; 0093 for (Uint32 i = 0; i < num_bytes; i++) { 0094 data[i] &= ~(data[i] & bs.data[i]); 0095 num_on += BitCount[data[i]]; 0096 } 0097 return *this; 0098 } 0099 0100 BitSet BitSet::operator-(const BitSet &bs) const 0101 { 0102 return BitSet(*this) -= bs; 0103 } 0104 0105 void BitSet::setAll(bool on) 0106 { 0107 std::fill(data, data + num_bytes, on ? 0xFF : 0x00); 0108 num_on = on ? num_bits : 0; 0109 } 0110 0111 void BitSet::clear() 0112 { 0113 setAll(false); 0114 } 0115 0116 void BitSet::orBitSet(const BitSet &other) 0117 { 0118 num_on = 0; 0119 0120 if (num_bits == other.num_bits) { 0121 // best case 0122 for (Uint32 i = 0; i < num_bytes; i++) { 0123 data[i] |= other.data[i]; 0124 num_on += BitCount[data[i]]; 0125 } 0126 return; 0127 } 0128 0129 // process till the end of other data or last-1 byte in our data 0130 // whatether comes first 0131 for (Uint32 i = 0; i < qMin(num_bytes - 1, other.num_bytes); i++) { 0132 data[i] |= other.data[i]; 0133 num_on += BitCount[data[i]]; 0134 } 0135 0136 // if last-1 not reached yet then the end of other data is reached 0137 // so just add BitCount till last-1 byte 0138 for (Uint32 i = other.num_bytes; i < num_bytes - 1; i++) { 0139 num_on += BitCount[data[i]]; 0140 } 0141 0142 // if other has matching byte for our last byte - OR it with proper mask 0143 if (other.num_bytes >= num_bytes) { 0144 data[num_bytes - 1] = (data[num_bytes - 1] | other.data[num_bytes - 1]) & tail_mask_lookup[num_bytes & 7]; 0145 } 0146 0147 // count bits set in last byte 0148 num_on += BitCount[data[num_bytes - 1]]; 0149 } 0150 0151 void BitSet::andBitSet(const BitSet &other) 0152 { 0153 num_on = 0; 0154 0155 if (num_bits == other.num_bits) { 0156 // best case 0157 for (Uint32 i = 0; i < num_bytes; i++) { 0158 data[i] &= other.data[i]; 0159 num_on += BitCount[data[i]]; 0160 } 0161 return; 0162 } 0163 0164 // we expect 0's at the tail of last byte (if any) 0165 // so just AND matching bytes and clear the others 0166 // no need to worry about mask for last byte 0167 for (Uint32 i = 0; i < qMin(num_bytes, other.num_bytes); i++) { 0168 data[i] &= other.data[i]; 0169 num_on += BitCount[data[i]]; 0170 } 0171 0172 if (num_bytes > other.num_bytes) { 0173 memset(data + other.num_bytes, 0, num_bytes - other.num_bytes); 0174 } 0175 } 0176 0177 bool BitSet::includesBitSet(const BitSet &other) const 0178 { 0179 if (num_bits == other.num_bits) { 0180 // best case 0181 for (Uint32 i = 0; i < num_bytes; i++) { 0182 if ((data[i] | other.data[i]) != data[i]) { 0183 return false; 0184 } 0185 } 0186 return true; 0187 } 0188 0189 // process till the end of other data or last-1 byte in our data 0190 // whatether comes first 0191 for (Uint32 i = 0; i < qMin(num_bytes - 1, other.num_bytes); i++) { 0192 if ((data[i] | other.data[i]) != data[i]) { 0193 return false; 0194 } 0195 } 0196 0197 // if other has matching byte for our last byte - OR it with proper mask 0198 if (other.num_bytes >= num_bytes) { 0199 const Uint8 d = data[num_bytes - 1]; 0200 if (((d | other.data[num_bytes - 1]) & tail_mask_lookup[num_bytes & 7]) != d) { 0201 return false; 0202 } 0203 } 0204 0205 return true; 0206 } 0207 0208 bool BitSet::allOn() const 0209 { 0210 return num_on == num_bits; 0211 } 0212 0213 bool BitSet::operator==(const BitSet &bs) const 0214 { 0215 if (this->getNumBits() != bs.getNumBits()) 0216 return false; 0217 0218 return memcmp(data, bs.data, num_bytes) == 0; 0219 } 0220 }