src/corelib/tools/qbitarray.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtCore module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
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     // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
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   QBitArray stream functions
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

Generated on Thu Mar 15 11:53:38 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1