liveMedia/BitVector.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2008 Live Networks, Inc.  All rights reserved.
00018 // Bit Vector data structure
00019 // Implementation
00020 
00021 #include "BitVector.hh"
00022 
00023 BitVector::BitVector(unsigned char* baseBytePtr,
00024                      unsigned baseBitOffset,
00025                      unsigned totNumBits) {
00026   setup(baseBytePtr, baseBitOffset, totNumBits);
00027 }
00028 
00029 void BitVector::setup(unsigned char* baseBytePtr,
00030                       unsigned baseBitOffset,
00031                       unsigned totNumBits) {
00032   fBaseBytePtr = baseBytePtr;
00033   fBaseBitOffset = baseBitOffset;
00034   fTotNumBits = totNumBits;
00035   fCurBitIndex = 0;
00036 }
00037 
00038 static unsigned char const singleBitMask[8]
00039     = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
00040 
00041 #define MAX_LENGTH 32
00042 
00043 void BitVector::putBits(unsigned from, unsigned numBits) {
00044   unsigned char tmpBuf[4];
00045   unsigned overflowingBits = 0;
00046 
00047   if (numBits > MAX_LENGTH) {
00048     numBits = MAX_LENGTH;
00049   }
00050 
00051   if (numBits > fTotNumBits - fCurBitIndex) {
00052     overflowingBits = numBits - (fTotNumBits - fCurBitIndex);
00053   }
00054 
00055   tmpBuf[0] = (unsigned char)(from>>24);
00056   tmpBuf[1] = (unsigned char)(from>>16);
00057   tmpBuf[2] = (unsigned char)(from>>8);
00058   tmpBuf[3] = (unsigned char)from;
00059 
00060   shiftBits(fBaseBytePtr, fBaseBitOffset + fCurBitIndex, /* to */
00061             tmpBuf, MAX_LENGTH - numBits, /* from */
00062             numBits - overflowingBits /* num bits */);
00063   fCurBitIndex += numBits - overflowingBits;
00064 }
00065 
00066 
00067 void BitVector::put1Bit(unsigned bit) {
00068   // The following is equivalent to "putBits(..., 1)", except faster:
00069   if (fCurBitIndex >= fTotNumBits) { /* overflow */
00070     return;
00071   } else {
00072     unsigned totBitOffset = fBaseBitOffset + fCurBitIndex++;
00073     unsigned char mask = singleBitMask[totBitOffset%8];
00074     if (bit) {
00075       fBaseBytePtr[totBitOffset/8] |= mask;
00076     } else {
00077       fBaseBytePtr[totBitOffset/8] &=~ mask;
00078     }
00079   }
00080 }
00081 
00082 
00083 unsigned BitVector::getBits(unsigned numBits) {
00084   unsigned char tmpBuf[4];
00085   unsigned overflowingBits = 0;
00086 
00087   if (numBits > MAX_LENGTH) {
00088     numBits = MAX_LENGTH;
00089   }
00090 
00091   if (numBits > fTotNumBits - fCurBitIndex) {
00092     overflowingBits = numBits - (fTotNumBits - fCurBitIndex);
00093   }
00094 
00095   shiftBits(tmpBuf, 0, /* to */
00096             fBaseBytePtr, fBaseBitOffset + fCurBitIndex, /* from */
00097             numBits - overflowingBits /* num bits */);
00098   fCurBitIndex += numBits - overflowingBits;
00099 
00100   unsigned result
00101     = (tmpBuf[0]<<24) | (tmpBuf[1]<<16) | (tmpBuf[2]<<8) | tmpBuf[3];
00102   result >>= (MAX_LENGTH - numBits); // move into low-order part of word
00103   result &= (0xFFFFFFFF << overflowingBits); // so any overflow bits are 0
00104   return result;
00105 }
00106 
00107 unsigned BitVector::get1Bit() {
00108   // The following is equivalent to "getBits(1)", except faster:
00109 
00110   if (fCurBitIndex >= fTotNumBits) { /* overflow */
00111     return 0;
00112   } else {
00113     unsigned totBitOffset = fBaseBitOffset + fCurBitIndex++;
00114     unsigned char curFromByte = fBaseBytePtr[totBitOffset/8];
00115     unsigned result = (curFromByte >> (7-(totBitOffset%8))) & 0x01;
00116     return result;
00117   }
00118 }
00119 
00120 void BitVector::skipBits(unsigned numBits) {
00121   if (numBits > fTotNumBits - fCurBitIndex) { /* overflow */
00122     fCurBitIndex = fTotNumBits;
00123   } else {
00124     fCurBitIndex += numBits;
00125   }
00126 }
00127 
00128 
00129 void shiftBits(unsigned char* toBasePtr, unsigned toBitOffset,
00130                unsigned char const* fromBasePtr, unsigned fromBitOffset,
00131                unsigned numBits) {
00132   /* Note that from and to may overlap, if from>to */
00133   unsigned char const* fromBytePtr = fromBasePtr + fromBitOffset/8;
00134   unsigned fromBitRem = fromBitOffset%8;
00135   unsigned char* toBytePtr = toBasePtr + toBitOffset/8;
00136   unsigned toBitRem = toBitOffset%8;
00137 
00138   while (numBits-- > 0) {
00139     unsigned char fromBitMask = singleBitMask[fromBitRem];
00140     unsigned char fromBit = (*fromBytePtr)&fromBitMask;
00141     unsigned char toBitMask = singleBitMask[toBitRem];
00142 
00143     if (fromBit != 0) {
00144       *toBytePtr |= toBitMask;
00145     } else {
00146       *toBytePtr &=~ toBitMask;
00147     }
00148 
00149     if (++fromBitRem == 8) {
00150       ++fromBytePtr;
00151       fromBitRem = 0;
00152     }
00153     if (++toBitRem == 8) {
00154       ++toBytePtr;
00155       toBitRem = 0;
00156     }
00157   }
00158 }

Generated on Tue Oct 7 15:38:08 2008 for live by  doxygen 1.5.2