00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qbitarray.h"
00025 #include <qdatastream.h>
00026 #include <qdebug.h>
00027 #include <string.h>
00028
00136 QBitArray::QBitArray(int size, bool value)
00137 {
00138 if (!size) {
00139 d.resize(0);
00140 return;
00141 }
00142 d.resize(1 + (size+7)/8);
00143 uchar* c = reinterpret_cast<uchar*>(d.data());
00144 memset(c, value ? 0xff : 0, d.size());
00145 *c = d.size()*8 - size;
00146 if (value && size && size % 8)
00147 *(c+1+size/8) &= (1 << (size%8)) - 1;
00148 }
00149
00167 int QBitArray::count(bool on) const
00168 {
00169 int numBits = 0;
00170 int len = size();
00171 #if 0
00172 for (int i = 0; i < len; ++i)
00173 numBits += testBit(i);
00174 #else
00175
00176 const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
00177 while (len >= 32) {
00178 quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16) | (quint32(bits[3]) << 24);
00179 quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
00180 c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
00181 c += ((v >> 24) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
00182 len -= 32;
00183 bits += 4;
00184 numBits += int(c);
00185 }
00186 while (len >= 24) {
00187 quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16);
00188 quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
00189 c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
00190 len -= 24;
00191 bits += 3;
00192 numBits += int(c);
00193 }
00194 while (len >= 0) {
00195 if (bits[len / 8] & (1 << ((len - 1) & 7)))
00196 ++numBits;
00197 --len;
00198 }
00199 #endif
00200 return on ? numBits : size() - numBits;
00201 }
00202
00215 void QBitArray::resize(int size)
00216 {
00217 if (!size) {
00218 d.resize(0);
00219 } else {
00220 int s = d.size();
00221 d.resize(1 + (size+7)/8);
00222 uchar* c = reinterpret_cast<uchar*>(d.data());
00223 if (size > (s << 3))
00224 memset(c + s, 0, d.size() - s);
00225 *c = d.size()*8 - size;
00226 }
00227 }
00228
00285 void QBitArray::fill(bool value, int begin, int end)
00286 {
00287 while (begin < end && begin & 0x7)
00288 setBit(begin++, value);
00289 int len = end - begin;
00290 if (len <= 0)
00291 return;
00292 int s = len & ~0x7;
00293 uchar *c = reinterpret_cast<uchar*>(d.data());
00294 memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
00295 begin += s;
00296 while (begin < end)
00297 setBit(begin++, value);
00298 }
00299
00485 QBitArray &QBitArray::operator&=(const QBitArray &other)
00486 {
00487 resize(qMax(size(), other.size()));
00488 uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
00489 const uchar *a2 = reinterpret_cast<const uchar*>(other.d.constData()) + 1;
00490 int n = other.d.size() -1 ;
00491 int p = d.size() - 1 - n;
00492 while (n-- > 0)
00493 *a1++ &= *a2++;
00494 while (p-- > 0)
00495 *a1++ = 0;
00496 return *this;
00497 }
00498
00520 QBitArray &QBitArray::operator|=(const QBitArray &other)
00521 {
00522 resize(qMax(size(), other.size()));
00523 uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
00524 const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
00525 int n = other.d.size() - 1;
00526 while (n-- > 0)
00527 *a1++ |= *a2++;
00528 return *this;
00529 }
00530
00552 QBitArray &QBitArray::operator^=(const QBitArray &other)
00553 {
00554 resize(qMax(size(), other.size()));
00555 uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
00556 const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
00557 int n = other.d.size() - 1;
00558 while (n-- > 0)
00559 *a1++ ^= *a2++;
00560 return *this;
00561 }
00562
00578 QBitArray QBitArray::operator~() const
00579 {
00580 int sz = size();
00581 QBitArray a(sz);
00582 const uchar *a1 = reinterpret_cast<const uchar *>(d.constData()) + 1;
00583 uchar *a2 = reinterpret_cast<uchar*>(a.d.data()) + 1;
00584 int n = d.size() - 1;
00585 while (n--)
00586 *a2++ = ~*a1++;
00587 if (sz && sz%8)
00588 *(a2-1) &= (1 << (sz%8)) - 1;
00589 return a;
00590 }
00591
00615 QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
00616 {
00617 QBitArray tmp = a1;
00618 tmp &= a2;
00619 return tmp;
00620 }
00621
00645 QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
00646 {
00647 QBitArray tmp = a1;
00648 tmp |= a2;
00649 return tmp;
00650 }
00651
00675 QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
00676 {
00677 QBitArray tmp = a1;
00678 tmp ^= a2;
00679 return tmp;
00680 }
00681
00723
00724
00725
00726
00734 #ifndef QT_NO_DATASTREAM
00735 QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
00736 {
00737 quint32 len = ba.size();
00738 out << len;
00739 if (len > 0)
00740 out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
00741 return out;
00742 }
00743
00752 QDataStream &operator>>(QDataStream &in, QBitArray &ba)
00753 {
00754 ba.clear();
00755 quint32 len;
00756 in >> len;
00757 if (len == 0) {
00758 ba.clear();
00759 return in;
00760 }
00761
00762 const quint32 Step = 8 * 1024 * 1024;
00763 quint32 totalBytes = (len + 7) / 8;
00764 quint32 allocated = 0;
00765
00766 while (allocated < totalBytes) {
00767 int blockSize = qMin(Step, totalBytes - allocated);
00768 ba.d.resize(allocated + blockSize + 1);
00769 if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
00770 ba.clear();
00771 in.setStatus(QDataStream::ReadPastEnd);
00772 return in;
00773 }
00774 allocated += blockSize;
00775 }
00776
00777 int paddingMask = ~((0x1 << (len & 0x7)) - 1);
00778 if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) {
00779 ba.clear();
00780 in.setStatus(QDataStream::ReadCorruptData);
00781 return in;
00782 }
00783
00784 *ba.d.data() = ba.d.size() * 8 - len;
00785 return in;
00786 }
00787 #endif