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-2013 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   if (numBits == 0) return; 
00045 
00046   unsigned char tmpBuf[4];
00047   unsigned overflowingBits = 0;
00048 
00049   if (numBits > MAX_LENGTH) {
00050     numBits = MAX_LENGTH;
00051   }
00052 
00053   if (numBits > fTotNumBits - fCurBitIndex) {
00054     overflowingBits = numBits - (fTotNumBits - fCurBitIndex);
00055   }
00056 
00057   tmpBuf[0] = (unsigned char)(from>>24);
00058   tmpBuf[1] = (unsigned char)(from>>16);
00059   tmpBuf[2] = (unsigned char)(from>>8);
00060   tmpBuf[3] = (unsigned char)from;
00061 
00062   shiftBits(fBaseBytePtr, fBaseBitOffset + fCurBitIndex, /* to */
00063             tmpBuf, MAX_LENGTH - numBits, /* from */
00064             numBits - overflowingBits /* num bits */);
00065   fCurBitIndex += numBits - overflowingBits;
00066 }
00067 
00068 void BitVector::put1Bit(unsigned bit) {
00069   // The following is equivalent to "putBits(..., 1)", except faster:
00070   if (fCurBitIndex >= fTotNumBits) { /* overflow */
00071     return;
00072   } else {
00073     unsigned totBitOffset = fBaseBitOffset + fCurBitIndex++;
00074     unsigned char mask = singleBitMask[totBitOffset%8];
00075     if (bit) {
00076       fBaseBytePtr[totBitOffset/8] |= mask;
00077     } else {
00078       fBaseBytePtr[totBitOffset/8] &=~ mask;
00079     }
00080   }
00081 }
00082 
00083 unsigned BitVector::getBits(unsigned numBits) {
00084   if (numBits == 0) return 0;
00085 
00086   unsigned char tmpBuf[4];
00087   unsigned overflowingBits = 0;
00088 
00089   if (numBits > MAX_LENGTH) {
00090     numBits = MAX_LENGTH;
00091   }
00092 
00093   if (numBits > fTotNumBits - fCurBitIndex) {
00094     overflowingBits = numBits - (fTotNumBits - fCurBitIndex);
00095   }
00096 
00097   shiftBits(tmpBuf, 0, /* to */
00098             fBaseBytePtr, fBaseBitOffset + fCurBitIndex, /* from */
00099             numBits - overflowingBits /* num bits */);
00100   fCurBitIndex += numBits - overflowingBits;
00101 
00102   unsigned result
00103     = (tmpBuf[0]<<24) | (tmpBuf[1]<<16) | (tmpBuf[2]<<8) | tmpBuf[3];
00104   result >>= (MAX_LENGTH - numBits); // move into low-order part of word
00105   result &= (0xFFFFFFFF << overflowingBits); // so any overflow bits are 0
00106   return result;
00107 }
00108 
00109 unsigned BitVector::get1Bit() {
00110   // The following is equivalent to "getBits(1)", except faster:
00111 
00112   if (fCurBitIndex >= fTotNumBits) { /* overflow */
00113     return 0;
00114   } else {
00115     unsigned totBitOffset = fBaseBitOffset + fCurBitIndex++;
00116     unsigned char curFromByte = fBaseBytePtr[totBitOffset/8];
00117     unsigned result = (curFromByte >> (7-(totBitOffset%8))) & 0x01;
00118     return result;
00119   }
00120 }
00121 
00122 void BitVector::skipBits(unsigned numBits) {
00123   if (numBits > fTotNumBits - fCurBitIndex) { /* overflow */
00124     fCurBitIndex = fTotNumBits;
00125   } else {
00126     fCurBitIndex += numBits;
00127   }
00128 }
00129 
00130 unsigned BitVector::get_expGolomb() {
00131   unsigned numLeadingZeroBits = 0;
00132   unsigned codeStart = 1;
00133 
00134   while (get1Bit() == 0 && fCurBitIndex < fTotNumBits) {
00135     ++numLeadingZeroBits;
00136     codeStart *= 2;
00137   }
00138 
00139   return codeStart -1 + getBits(numLeadingZeroBits);
00140 }
00141 
00142 
00143 void shiftBits(unsigned char* toBasePtr, unsigned toBitOffset,
00144                unsigned char const* fromBasePtr, unsigned fromBitOffset,
00145                unsigned numBits) {
00146   if (numBits == 0) return;
00147 
00148   /* Note that from and to may overlap, if from>to */
00149   unsigned char const* fromBytePtr = fromBasePtr + fromBitOffset/8;
00150   unsigned fromBitRem = fromBitOffset%8;
00151   unsigned char* toBytePtr = toBasePtr + toBitOffset/8;
00152   unsigned toBitRem = toBitOffset%8;
00153 
00154   while (numBits-- > 0) {
00155     unsigned char fromBitMask = singleBitMask[fromBitRem];
00156     unsigned char fromBit = (*fromBytePtr)&fromBitMask;
00157     unsigned char toBitMask = singleBitMask[toBitRem];
00158 
00159     if (fromBit != 0) {
00160       *toBytePtr |= toBitMask;
00161     } else {
00162       *toBytePtr &=~ toBitMask;
00163     }
00164 
00165     if (++fromBitRem == 8) {
00166       ++fromBytePtr;
00167       fromBitRem = 0;
00168     }
00169     if (++toBitRem == 8) {
00170       ++toBytePtr;
00171       toBitRem = 0;
00172     }
00173   }
00174 }

Generated on Mon Apr 29 13:28:01 2013 for live by  doxygen 1.5.2