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 xoreos' 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 MSB2LSB>
00047 class BitStreamImpl {
00048 private:
00049     STREAM *_stream;            
00050     DisposeAfterUse::Flag _disposeAfterUse; 
00051 
00052     uint64 _bitContainer; 
00053     uint8  _bitsLeft; 
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 fillContainer(size_t min) {
00081         while (_bitsLeft < min) {
00082 
00083             uint64 data;
00084             if (_pos + _bitsLeft + valueBits <= _size) {
00085                 data = readData();
00086             } else {
00087                 // Peeking data out of bounds is well defined and returns 0 bits.
00088                 // This is for convenience when using speed-up techniques reading
00089                 // more bits than actually available. Users should call eos() to
00090                 // check if data was actually read out of bounds. Peeking out of
00091                 // bounds does not set the eos flag.
00092                 data = 0;
00093             }
00094 
00095             // Move the data value to the right position in the bit container
00096             if (MSB2LSB)
00097                 _bitContainer |= data << (64 - valueBits - _bitsLeft);
00098             else
00099                 _bitContainer |= data << _bitsLeft;
00100 
00101             _bitsLeft += valueBits;
00102         }
00103 }
00104 
00106     inline static uint32 getNBits(uint64 value, size_t n) {
00107         if (n == 0)
00108             return 0;
00109 
00110         const size_t toShift = 64 - n;
00111 
00112         if (MSB2LSB)
00113             return value >> toShift;
00114         else
00115             return (value << toShift) >> toShift;
00116     }
00117 
00119     inline void skipBits(size_t n) {
00120         assert(n <= _bitsLeft);
00121 
00122         // Shift to the next bit
00123         if (MSB2LSB)
00124             _bitContainer <<= n;
00125         else
00126             _bitContainer >>= n;
00127 
00128         _bitsLeft -= n;
00129         _pos += n;
00130     }
00131 
00132 public:
00134     BitStreamImpl(STREAM *stream, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::NO) :
00135         _stream(stream), _disposeAfterUse(disposeAfterUse), _bitContainer(0), _bitsLeft(0), _pos(0) {
00136 
00137         if ((valueBits != 8) && (valueBits != 16) && (valueBits != 32))
00138             error("BitStreamImpl: Invalid memory layout %d, %d, %d", valueBits, isLE, MSB2LSB);
00139 
00140         _size = (_stream->size() & ~((uint32) ((valueBits >> 3) - 1))) * 8;
00141     }
00142 
00144     BitStreamImpl(STREAM &stream) :
00145         _stream(&stream), _disposeAfterUse(DisposeAfterUse::NO), _bitContainer(0), _bitsLeft(0), _pos(0) {
00146 
00147         if ((valueBits != 8) && (valueBits != 16) && (valueBits != 32))
00148             error("BitStreamImpl: Invalid memory layout %d, %d, %d", valueBits, isLE, MSB2LSB);
00149 
00150         _size = (_stream->size() & ~((uint32) ((valueBits >> 3) - 1))) * 8;
00151     }
00152 
00153     ~BitStreamImpl() {
00154         if (_disposeAfterUse == DisposeAfterUse::YES)
00155             delete _stream;
00156     }
00157 
00159     uint peekBit() {
00160         fillContainer(1);
00161 
00162         return getNBits(_bitContainer, 1);
00163     }
00164 
00166     uint getBit() {
00167         const uint b = peekBit();
00168 
00169         skipBits(1);
00170 
00171         return b;
00172     }
00173 
00179     uint32 peekBits(size_t n) {
00180         if (n > 32)
00181             error("BitStreamImpl::peekBits(): Too many bits requested to be peeked");
00182 
00183         fillContainer(n);
00184         return getNBits(_bitContainer, n);
00185     }
00186 
00197     uint32 getBits(size_t n) {
00198         if (n > 32)
00199             error("BitStreamImpl::getBits(): Too many bits requested to be read");
00200 
00201         const uint32 b = peekBits(n);
00202 
00203         skipBits(n);
00204 
00205         return b;
00206     }
00207 
00219     void addBit(uint32 &x, uint32 n) {
00220         if (n >= 32)
00221             error("BitStreamImpl::addBit(): Too many bits requested to be read");
00222 
00223         if (MSB2LSB)
00224             x = (x << 1) | getBit();
00225         else
00226             x = (x & ~(1 << n)) | (getBit() << n);
00227     }
00228 
00230     void rewind() {
00231         _stream->seek(0);
00232 
00233         _bitContainer = 0;
00234         _bitsLeft     = 0;
00235         _pos          = 0;
00236     }
00237 
00239     void skip(uint32 n) {
00240         while (n > 32) {
00241             fillContainer(32);
00242             skipBits(32);
00243             n -= 32;
00244         }
00245 
00246         fillContainer(n);
00247         skipBits(n);
00248     }
00249 
00251     void align() {
00252         uint32 bitsAfterBoundary = _pos % valueBits;
00253         if (bitsAfterBoundary) {
00254             skip(valueBits - bitsAfterBoundary);
00255         }
00256     }
00257 
00259     uint32 pos() const {
00260         return _pos;
00261     }
00262 
00264     uint32 size() const {
00265         return _size;
00266     }
00267 
00268     bool eos() const {
00269         return _stream->eos() || (_pos >= _size);
00270     }
00271 
00272     static bool isMSB2LSB() {
00273         return MSB2LSB;
00274     }
00275 };
00276 
00277 
00278 
00288 class BitStreamMemoryStream {
00289 private:
00290     const byte * const _ptrOrig;
00291     const byte *_ptr;
00292     const uint32 _size;
00293     uint32 _pos;
00294     DisposeAfterUse::Flag _disposeMemory;
00295     bool _eos;
00296 
00297 public:
00298     BitStreamMemoryStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
00299         _ptrOrig(dataPtr),
00300         _ptr(dataPtr),
00301         _size(dataSize),
00302         _pos(0),
00303         _disposeMemory(disposeMemory),
00304         _eos(false) {}
00305 
00306     ~BitStreamMemoryStream() {
00307         if (_disposeMemory)
00308             free(const_cast<byte *>(_ptrOrig));
00309     }
00310 
00311     bool eos() const {
00312         return _eos;
00313     }
00314 
00315     bool err() const {
00316         return false;
00317     }
00318 
00319     int32 pos() const {
00320         return _pos;
00321     }
00322 
00323     int32 size() const {
00324         return _size;
00325     }
00326 
00327     bool seek(uint32 offset) {
00328         assert(offset <= _size);
00329 
00330         _eos = false;
00331         _pos = offset;
00332         _ptr = _ptrOrig + _pos;
00333         return true;
00334     }
00335 
00336     byte readByte() {
00337         if (_pos >= _size) {
00338             _eos = true;
00339             return 0;
00340         }
00341 
00342         _pos++;
00343         return *_ptr++;
00344     }
00345 
00346     uint16 readUint16LE() {
00347         if (_pos + 2 > _size) {
00348             _eos = true;
00349             if (_pos < _size) {
00350                 _pos++;
00351                 return *_ptr++;
00352             } else {
00353                 return 0;
00354             }
00355         }
00356 
00357         uint16 val = READ_LE_UINT16(_ptr);
00358 
00359         _pos += 2;
00360         _ptr += 2;
00361 
00362         return val;
00363     }
00364 
00365     uint16 readUint16BE() {
00366         if (_pos + 2 > _size) {
00367             _eos = true;
00368             if (_pos < _size) {
00369                 _pos++;
00370                 return (*_ptr++) << 8;
00371             } else {
00372                 return 0;
00373             }
00374         }
00375 
00376         uint16 val = READ_LE_UINT16(_ptr);
00377 
00378         _pos += 2;
00379         _ptr += 2;
00380 
00381         return val;
00382     }
00383 
00384     uint32 readUint32LE() {
00385         if (_pos + 4 > _size) {
00386             uint32 val = readByte();
00387             val |= (uint32)readByte() << 8;
00388             val |= (uint32)readByte() << 16;
00389             val |= (uint32)readByte() << 24;
00390 
00391             return val;
00392         }
00393 
00394         uint32 val = READ_LE_UINT32(_ptr);
00395 
00396         _pos += 4;
00397         _ptr += 4;
00398 
00399         return val;
00400     }
00401 
00402     uint32 readUint32BE() {
00403         if (_pos + 4 > _size) {
00404             uint32 val = (uint32)readByte() << 24;
00405             val |= (uint32)readByte() << 16;
00406             val |= (uint32)readByte() << 8;
00407             val |= (uint32)readByte();
00408 
00409             return val;
00410         }
00411 
00412         uint32 val = READ_BE_UINT32(_ptr);
00413 
00414         _pos += 4;
00415         _ptr += 4;
00416 
00417         return val;
00418     }
00419 
00420 };
00421 
00422 
00423 // typedefs for various memory layouts.
00424 
00426 typedef BitStreamImpl<SeekableReadStream, 8, false, true > BitStream8MSB;
00428 typedef BitStreamImpl<SeekableReadStream, 8, false, false> BitStream8LSB;
00429 
00431 typedef BitStreamImpl<SeekableReadStream, 16, true , true > BitStream16LEMSB;
00433 typedef BitStreamImpl<SeekableReadStream, 16, true , false> BitStream16LELSB;
00435 typedef BitStreamImpl<SeekableReadStream, 16, false, true > BitStream16BEMSB;
00437 typedef BitStreamImpl<SeekableReadStream, 16, false, false> BitStream16BELSB;
00438 
00440 typedef BitStreamImpl<SeekableReadStream, 32, true , true > BitStream32LEMSB;
00442 typedef BitStreamImpl<SeekableReadStream, 32, true , false> BitStream32LELSB;
00444 typedef BitStreamImpl<SeekableReadStream, 32, false, true > BitStream32BEMSB;
00446 typedef BitStreamImpl<SeekableReadStream, 32, false, false> BitStream32BELSB;
00447 
00448 
00449 
00451 typedef BitStreamImpl<BitStreamMemoryStream, 8, false, true > BitStreamMemory8MSB;
00453 typedef BitStreamImpl<BitStreamMemoryStream, 8, false, false> BitStreamMemory8LSB;
00454 
00456 typedef BitStreamImpl<BitStreamMemoryStream, 16, true , true > BitStreamMemory16LEMSB;
00458 typedef BitStreamImpl<BitStreamMemoryStream, 16, true , false> BitStreamMemory16LELSB;
00460 typedef BitStreamImpl<BitStreamMemoryStream, 16, false, true > BitStreamMemory16BEMSB;
00462 typedef BitStreamImpl<BitStreamMemoryStream, 16, false, false> BitStreamMemory16BELSB;
00463 
00465 typedef BitStreamImpl<BitStreamMemoryStream, 32, true , true > BitStreamMemory32LEMSB;
00467 typedef BitStreamImpl<BitStreamMemoryStream, 32, true , false> BitStreamMemory32LELSB;
00469 typedef BitStreamImpl<BitStreamMemoryStream, 32, false, true > BitStreamMemory32BEMSB;
00471 typedef BitStreamImpl<BitStreamMemoryStream, 32, false, false> BitStreamMemory32BELSB;
00472 
00473 
00474 } // End of namespace Common
00475 
00476 #endif // COMMON_BITSTREAM_H


Generated on Sat Nov 9 2019 05:00:25 for ResidualVM by doxygen 1.7.1
curved edge   curved edge