ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

bitstream.h

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 // Based on eos' BitStream implementation
00024 
00025 #ifndef COMMON_BITSTREAM_H
00026 #define COMMON_BITSTREAM_H
00027 
00028 #include "common/scummsys.h"
00029 #include "common/textconsole.h"
00030 #include "common/stream.h"
00031 #include "common/types.h"
00032 #include "common/util.h"
00033 
00034 namespace Common {
00035 
00046 template<class STREAM, int valueBits, bool isLE, bool isMSB2LSB>
00047 class BitStreamImpl {
00048 private:
00049     STREAM *_stream;            
00050     DisposeAfterUse::Flag _disposeAfterUse; 
00051 
00052     uint32 _value;   
00053     uint8  _inValue; 
00054     uint32 _size;    
00055     uint32 _pos;     
00056 
00058     inline uint32 readData() {
00059         if (isLE) {
00060             if (valueBits ==  8)
00061                 return _stream->readByte();
00062             if (valueBits == 16)
00063                 return _stream->readUint16LE();
00064             if (valueBits == 32)
00065                 return _stream->readUint32LE();
00066         } else {
00067             if (valueBits ==  8)
00068                 return _stream->readByte();
00069             if (valueBits == 16)
00070                 return _stream->readUint16BE();
00071             if (valueBits == 32)
00072                 return _stream->readUint32BE();
00073         }
00074 
00075         assert(false);
00076         return 0;
00077     }
00078 
00080     inline void readValue() {
00081         if (_size - _pos < valueBits)
00082             error("BitStreamImpl::readValue(): End of bit stream reached");
00083 
00084         _value = readData();
00085         if (_stream->err() || _stream->eos())
00086             error("BitStreamImpl::readValue(): Read error");
00087 
00088         // If we're reading the bits MSB first, we need to shift the value to that position
00089         if (isMSB2LSB)
00090             _value <<= 32 - valueBits;
00091         }
00092 
00093 public:
00095     BitStreamImpl(STREAM *stream, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::NO) :
00096         _stream(stream), _disposeAfterUse(disposeAfterUse), _value(0), _inValue(0), _pos(0) {
00097 
00098         if ((valueBits != 8) && (valueBits != 16) && (valueBits != 32))
00099             error("BitStreamImpl: Invalid memory layout %d, %d, %d", valueBits, isLE, isMSB2LSB);
00100 
00101         _size = (_stream->size() & ~((uint32) ((valueBits >> 3) - 1))) * 8;
00102     }
00103 
00105     BitStreamImpl(STREAM &stream) :
00106         _stream(&stream), _disposeAfterUse(DisposeAfterUse::NO), _value(0), _inValue(0), _pos(0) {
00107 
00108         if ((valueBits != 8) && (valueBits != 16) && (valueBits != 32))
00109             error("BitStreamImpl: Invalid memory layout %d, %d, %d", valueBits, isLE, isMSB2LSB);
00110 
00111         _size = (_stream->size() & ~((uint32) ((valueBits >> 3) - 1))) * 8;
00112     }
00113 
00114     ~BitStreamImpl() {
00115         if (_disposeAfterUse == DisposeAfterUse::YES)
00116             delete _stream;
00117     }
00118 
00119 private:
00120     uint32 getBit_internal() {
00121         // Get the current bit
00122         uint32 b = 0;
00123         if (isMSB2LSB)
00124             b = ((_value & 0x80000000) == 0) ? 0 : 1;
00125         else
00126             b = ((_value & 1) == 0) ? 0 : 1;
00127 
00128         // Shift to the next bit
00129         if (isMSB2LSB)
00130             _value <<= 1;
00131         else
00132             _value >>= 1;
00133 
00134         return b;
00135     }
00136 
00137 public:
00139     uint32 getBit() {
00140         // Check if we need the next value
00141         if (_inValue == 0)
00142             readValue();
00143 
00144         uint32 b = getBit_internal();
00145 
00146         // Increase the position within the current value
00147         _inValue = (_inValue + 1) % valueBits;
00148         _pos++;
00149 
00150         return b;
00151     }
00152 
00163     uint32 getBits(uint8 n) {
00164         if (n == 0)
00165             return 0;
00166 
00167         if (n > 32)
00168             error("BitStreamImpl::getBits(): Too many bits requested to be read");
00169 
00170         // Read the number of bits
00171         uint32 v = 0;
00172 
00173         uint8 nOrig = n;
00174         if (_inValue) {
00175             int count = MIN((int)n, valueBits - _inValue);
00176             for (int i = 0; i < count; ++i) {
00177                 if (isMSB2LSB) {
00178                     v = (v << 1) | getBit_internal();
00179                 } else {
00180                     v = (v >> 1) | (getBit_internal() << 31);
00181                 }
00182             }
00183 
00184             n -= count;
00185         }
00186 
00187         while (n > 0) {
00188             // NB: readValue doesn't care that _inValue is incorrect here
00189             readValue();
00190 
00191             int count = MIN((int)n, valueBits);
00192             for (int i = 0; i < count; ++i) {
00193                 if (isMSB2LSB) {
00194                     v = (v << 1) | getBit_internal();
00195                 } else {
00196                     v = (v >> 1) | (getBit_internal() << 31);
00197                 }
00198             }
00199 
00200             n -= count;
00201         }
00202 
00203         _inValue = (_inValue + nOrig) % valueBits;
00204         _pos += nOrig;
00205 
00206         if (!isMSB2LSB)
00207             v >>= (32 - nOrig);
00208 
00209         return v;
00210     }
00211 
00213     uint32 peekBit() {
00214         uint32 value   = _value;
00215         uint8  inValue = _inValue;
00216         uint32 curStreamPos  = _stream->pos();
00217         uint32 curPos = _pos;
00218 
00219         uint32 v = getBit();
00220 
00221         _pos     = curPos;
00222         _stream->seek(curStreamPos);
00223         _inValue = inValue;
00224         _value   = value;
00225 
00226         return v;
00227     }
00228 
00234     uint32 peekBits(uint8 n) {
00235         uint32 value   = _value;
00236         uint8  inValue = _inValue;
00237         uint32 curStreamPos  = _stream->pos();
00238         uint32 curPos = _pos;
00239 
00240         uint32 v = getBits(n);
00241 
00242         _pos     = curPos;
00243         _stream->seek(curStreamPos);
00244         _inValue = inValue;
00245         _value   = value;
00246 
00247         return v;
00248     }
00249 
00261     void addBit(uint32 &x, uint32 n) {
00262         if (n >= 32)
00263             error("BitStreamImpl::addBit(): Too many bits requested to be read");
00264 
00265         if (isMSB2LSB)
00266             x = (x << 1) | getBit();
00267         else
00268             x = (x & ~(1 << n)) | (getBit() << n);
00269     }
00270 
00272     void rewind() {
00273         _stream->seek(0);
00274 
00275         _value   = 0;
00276         _inValue = 0;
00277         _pos     = 0;
00278     }
00279 
00281     void skip(uint32 n) {
00282         while (n-- > 0)
00283             getBit();
00284     }
00285 
00287     void align() {
00288         while (_inValue)
00289             getBit();
00290     }
00291 
00293     uint32 pos() const {
00294         return _pos;
00295     }
00296 
00298     uint32 size() const {
00299         return _size;
00300     }
00301 
00302     bool eos() const {
00303         return _stream->eos() || (_pos >= _size);
00304     }
00305 };
00306 
00307 
00308 
00318 class BitStreamMemoryStream {
00319 private:
00320     const byte * const _ptrOrig;
00321     const byte *_ptr;
00322     const uint32 _size;
00323     uint32 _pos;
00324     DisposeAfterUse::Flag _disposeMemory;
00325     bool _eos;
00326 
00327 public:
00328     BitStreamMemoryStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
00329         _ptrOrig(dataPtr),
00330         _ptr(dataPtr),
00331         _size(dataSize),
00332         _pos(0),
00333         _disposeMemory(disposeMemory),
00334         _eos(false) {}
00335 
00336     ~BitStreamMemoryStream() {
00337         if (_disposeMemory)
00338             free(const_cast<byte *>(_ptrOrig));
00339     }
00340 
00341     bool eos() const {
00342         return _eos;
00343     }
00344 
00345     bool err() const {
00346         return false;
00347     }
00348 
00349     int32 pos() const {
00350         return _pos;
00351     }
00352 
00353     int32 size() const {
00354         return _size;
00355     }
00356 
00357     bool seek(uint32 offset) {
00358         assert(offset <= _size);
00359 
00360         _eos = false;
00361         _pos = offset;
00362         _ptr = _ptrOrig + _pos;
00363         return true;
00364     }
00365 
00366     byte readByte() {
00367         if (_pos >= _size) {
00368             _eos = true;
00369             return 0;
00370         }
00371 
00372         _pos++;
00373         return *_ptr++;
00374     }
00375 
00376     uint16 readUint16LE() {
00377         if (_pos + 2 > _size) {
00378             _eos = true;
00379             if (_pos < _size) {
00380                 _pos++;
00381                 return *_ptr++;
00382             } else {
00383                 return 0;
00384             }
00385         }
00386 
00387         uint16 val = READ_LE_UINT16(_ptr);
00388 
00389         _pos += 2;
00390         _ptr += 2;
00391 
00392         return val;
00393     }
00394 
00395     uint16 readUint16BE() {
00396         if (_pos + 2 > _size) {
00397             _eos = true;
00398             if (_pos < _size) {
00399                 _pos++;
00400                 return (*_ptr++) << 8;
00401             } else {
00402                 return 0;
00403             }
00404         }
00405 
00406         uint16 val = READ_LE_UINT16(_ptr);
00407 
00408         _pos += 2;
00409         _ptr += 2;
00410 
00411         return val;
00412     }
00413 
00414     uint32 readUint32LE() {
00415         if (_pos + 4 > _size) {
00416             uint32 val = readByte();
00417             val |= (uint32)readByte() << 8;
00418             val |= (uint32)readByte() << 16;
00419             val |= (uint32)readByte() << 24;
00420 
00421             return val;
00422         }
00423 
00424         uint32 val = READ_LE_UINT32(_ptr);
00425 
00426         _pos += 4;
00427         _ptr += 4;
00428 
00429         return val;
00430     }
00431 
00432     uint32 readUint32BE() {
00433         if (_pos + 4 > _size) {
00434             uint32 val = (uint32)readByte() << 24;
00435             val |= (uint32)readByte() << 16;
00436             val |= (uint32)readByte() << 8;
00437             val |= (uint32)readByte();
00438 
00439             return val;
00440         }
00441 
00442         uint32 val = READ_BE_UINT32(_ptr);
00443 
00444         _pos += 4;
00445         _ptr += 4;
00446 
00447         return val;
00448     }
00449 
00450 };
00451 
00452 
00453 // typedefs for various memory layouts.
00454 
00456 typedef BitStreamImpl<SeekableReadStream, 8, false, true > BitStream8MSB;
00458 typedef BitStreamImpl<SeekableReadStream, 8, false, false> BitStream8LSB;
00459 
00461 typedef BitStreamImpl<SeekableReadStream, 16, true , true > BitStream16LEMSB;
00463 typedef BitStreamImpl<SeekableReadStream, 16, true , false> BitStream16LELSB;
00465 typedef BitStreamImpl<SeekableReadStream, 16, false, true > BitStream16BEMSB;
00467 typedef BitStreamImpl<SeekableReadStream, 16, false, false> BitStream16BELSB;
00468 
00470 typedef BitStreamImpl<SeekableReadStream, 32, true , true > BitStream32LEMSB;
00472 typedef BitStreamImpl<SeekableReadStream, 32, true , false> BitStream32LELSB;
00474 typedef BitStreamImpl<SeekableReadStream, 32, false, true > BitStream32BEMSB;
00476 typedef BitStreamImpl<SeekableReadStream, 32, false, false> BitStream32BELSB;
00477 
00478 
00479 
00481 typedef BitStreamImpl<BitStreamMemoryStream, 8, false, true > BitStreamMemory8MSB;
00483 typedef BitStreamImpl<BitStreamMemoryStream, 8, false, false> BitStreamMemory8LSB;
00484 
00486 typedef BitStreamImpl<BitStreamMemoryStream, 16, true , true > BitStreamMemory16LEMSB;
00488 typedef BitStreamImpl<BitStreamMemoryStream, 16, true , false> BitStreamMemory16LELSB;
00490 typedef BitStreamImpl<BitStreamMemoryStream, 16, false, true > BitStreamMemory16BEMSB;
00492 typedef BitStreamImpl<BitStreamMemoryStream, 16, false, false> BitStreamMemory16BELSB;
00493 
00495 typedef BitStreamImpl<BitStreamMemoryStream, 32, true , true > BitStreamMemory32LEMSB;
00497 typedef BitStreamImpl<BitStreamMemoryStream, 32, true , false> BitStreamMemory32LELSB;
00499 typedef BitStreamImpl<BitStreamMemoryStream, 32, false, true > BitStreamMemory32BEMSB;
00501 typedef BitStreamImpl<BitStreamMemoryStream, 32, false, false> BitStreamMemory32BELSB;
00502 
00503 
00504 } // End of namespace Common
00505 
00506 #endif // COMMON_BITSTREAM_H


Generated on Sat Mar 16 2019 05:01:20 for ResidualVM by doxygen 1.7.1
curved edge   curved edge