xoreos  0.0.5
bitstream.h
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #ifndef COMMON_BITSTREAM_H
26 #define COMMON_BITSTREAM_H
27 
28 #include <cassert>
29 
30 #include <boost/noncopyable.hpp>
31 
32 #include "src/common/types.h"
34 #include "src/common/error.h"
35 #include "src/common/readstream.h"
36 
37 namespace Common {
38 
40 class BitStream {
41 public:
42  virtual ~BitStream() {
43  }
44 
46  virtual size_t pos() const = 0;
47 
49  virtual size_t size() const = 0;
50 
52  virtual bool eos() const = 0;
53 
55  virtual void rewind() = 0;
56 
58  virtual void skip(size_t n) = 0;
59 
61  virtual uint32 getBit() = 0;
62 
64  virtual uint32 getBits(size_t n) = 0;
65 
67  virtual void addBit(uint32 &x, size_t n) = 0;
68 
69 protected:
71  }
72 };
73 
84 template<int valueBits, bool isLE, bool isMSB2LSB>
85 class BitStreamImpl : boost::noncopyable, public BitStream {
86 private:
88 
91 
93  inline uint64 readData() {
94  if (isLE) {
95  if (valueBits == 8)
96  return _stream->readByte();
97  if (valueBits == 16)
98  return _stream->readUint16LE();
99  if (valueBits == 32)
100  return _stream->readUint32LE();
101  if (valueBits == 64)
102  return _stream->readUint64LE();
103  } else {
104  if (valueBits == 8)
105  return _stream->readByte();
106  if (valueBits == 16)
107  return _stream->readUint16BE();
108  if (valueBits == 32)
109  return _stream->readUint32BE();
110  if (valueBits == 64)
111  return _stream->readUint64BE();
112  }
113 
114  assert(false);
115  return 0;
116  }
117 
119  inline void readValue() {
120  if ((size() - pos()) < valueBits)
121  throw Exception("BitStream::readValue(): End of bit stream reached");
122 
123  _value = readData();
124 
125  // If we're reading the bits MSB first, we need to shift the value to that position
126  if (isMSB2LSB)
127  _value <<= 64 - valueBits;
128  }
129 
130 public:
132  BitStreamImpl(SeekableReadStream *stream, bool disposeAfterUse = false) :
133  _stream(stream, disposeAfterUse), _value(0), _inValue(0) {
134 
135  assert(_stream);
136 
137  if ((valueBits != 8) && (valueBits != 16) && (valueBits != 32) && (valueBits != 64))
138  throw Exception("BitStream: Invalid memory layout %d, %d, %d", valueBits, isLE, isMSB2LSB);
139  }
140 
143  _stream(&stream, false), _value(0), _inValue(0) {
144 
145  if ((valueBits != 8) && (valueBits != 16) && (valueBits != 32) && (valueBits != 64))
146  throw Exception("BitStream: Invalid memory layout %d, %d, %d", valueBits, isLE, isMSB2LSB);
147  }
148 
150  }
151 
154  // Check if we need the next value
155  if (_inValue == 0)
156  readValue();
157 
158  // Get the current bit
159  int b = 0;
160  if (isMSB2LSB)
161  b = ((_value & 0x8000000000000000ULL) == 0) ? 0 : 1;
162  else
163  b = ((_value & 1) == 0) ? 0 : 1;
164 
165  // Shift to the next bit
166  if (isMSB2LSB)
167  _value <<= 1;
168  else
169  _value >>= 1;
170 
171  // Increase the position within the current value
172  _inValue = (_inValue + 1) % valueBits;
173 
174  return b;
175  }
176 
178  uint32 getBits(size_t n) {
179  if (n == 0)
180  return 0;
181 
182  if (n > 32)
183  throw Exception("Too many bits requested to be read");
184 
185  // Read the number of bits
186  uint32 v = 0;
187 
188  if (isMSB2LSB) {
189  while (n-- > 0)
190  v = (v << 1) | getBit();
191  } else {
192  for (uint32 i = 0; i < n; i++)
193  v = (v >> 1) | (((uint32) getBit()) << 31);
194 
195  v >>= (32 - n);
196  }
197 
198  return v;
199  }
200 
202  void addBit(uint32 &x, size_t n) {
203  if (n >= 32)
204  throw Exception("Too many bits requested to be read");
205 
206  if (isMSB2LSB)
207  x = (x << 1) | getBit();
208  else
209  x = (x & ~(1 << n)) | (getBit() << n);
210  }
211 
213  void rewind() {
214  _stream->seek(0);
215 
216  _value = 0;
217  _inValue = 0;
218  }
219 
221  void skip(size_t n) {
222  while (n-- > 0)
223  getBit();
224  }
225 
227  size_t pos() const {
228  if (_stream->pos() == 0)
229  return 0;
230 
231  size_t p = (_inValue == 0) ? _stream->pos() : ((_stream->pos() - 1) & ~((size_t) ((valueBits >> 3) - 1)));
232  return p * 8 + _inValue;
233  }
234 
236  size_t size() const {
237  return (_stream->size() & ~((size_t) ((valueBits >> 3) - 1))) * 8;
238  }
239 
240  bool eos() const {
241  return _stream->eos() || (pos() >= size());
242  }
243 };
244 
245 // typedefs for various memory layouts.
246 
251 
260 
269 
278 
279 } // End of namespace Common
280 
281 #endif // COMMON_BITSTREAM_H
BitStreamImpl< 32, true, true > BitStream32LEMSB
32-bit little-endian data, MSB to LSB.
Definition: bitstream.h:262
BitStreamImpl< 16, true, false > BitStream16LELSB
16-bit little-endian data, LSB to MSB.
Definition: bitstream.h:255
Definition: 2dafile.h:39
uint64_t uint64
Definition: types.h:206
uint8_t uint8
Definition: types.h:200
virtual size_t pos() const =0
Return the stream position in bits.
BitStreamImpl< 64, true, true > BitStream64LEMSB
64-bit little-endian data, MSB to LSB.
Definition: bitstream.h:271
void rewind()
Rewind the bit stream back to the start.
Definition: bitstream.h:213
BitStreamImpl< 16, false, false > BitStream16BELSB
16-bit big-endian data, LSB to MSB.
Definition: bitstream.h:259
uint32 getBit()
Read a bit from the bit stream.
Definition: bitstream.h:153
uint32 getBits(size_t n)
Read a multi-bit value from the bit stream.
Definition: bitstream.h:178
BitStreamImpl< 16, false, true > BitStream16BEMSB
16-bit big-endian data, MSB to LSB.
Definition: bitstream.h:257
BitStreamImpl< 16, true, true > BitStream16LEMSB
16-bit little-endian data, MSB to LSB.
Definition: bitstream.h:253
size_t pos() const
Return the stream position in bits.
Definition: bitstream.h:227
virtual void rewind()=0
Rewind the bit stream back to the start.
BitStreamImpl< 32, true, false > BitStream32LELSB
32-bit little-endian data, LSB to MSB.
Definition: bitstream.h:264
void readValue()
Read the next data value.
Definition: bitstream.h:119
BitStreamImpl< 32, false, false > BitStream32BELSB
32-bit big-endian data, LSB to MSB.
Definition: bitstream.h:268
Basic exceptions to throw.
uint8 _inValue
Position within the current value.
Definition: bitstream.h:90
BitStreamImpl< 8, false, false > BitStream8LSB
8-bit data, LSB to MSB.
Definition: bitstream.h:250
virtual bool eos() const =0
Has the end of the stream been reached?
uint64 readData()
Read a data value.
Definition: bitstream.h:93
virtual uint32 getBit()=0
Read a bit from the bit stream.
BitStreamImpl(SeekableReadStream *stream, bool disposeAfterUse=false)
Create a bit stream using this input data stream and optionally delete it on destruction.
Definition: bitstream.h:132
Low-level type definitions to handle fixed width types portably.
StackException Exception
Definition: error.h:59
virtual ~BitStream()
Definition: bitstream.h:42
BitStreamImpl(SeekableReadStream &stream)
Create a bit stream using this input data stream.
Definition: bitstream.h:142
uint64 _value
Current value.
Definition: bitstream.h:89
Basic reading stream interfaces.
A disposable plain pointer, allowing pointer-y access and normal deletion.
void skip(size_t n)
Skip the specified amount of bits.
Definition: bitstream.h:221
A smart pointer with a deletion flag.
size_t size() const
Return the stream size in bits.
Definition: bitstream.h:236
virtual void addBit(uint32 &x, size_t n)=0
Add a bit to the n-bit value x, making it an (n+1)-bit value.
void addBit(uint32 &x, size_t n)
Add a bit to the n-bit value x, making it an (n+1)-bit value.
Definition: bitstream.h:202
virtual void skip(size_t n)=0
Skip the specified amount of bits.
bool eos() const
Has the end of the stream been reached?
Definition: bitstream.h:240
uint32_t uint32
Definition: types.h:204
DisposablePtr< SeekableReadStream > _stream
The input stream.
Definition: bitstream.h:87
virtual uint32 getBits(size_t n)=0
Read a multi-bit value from the bit stream.
BitStreamImpl< 32, false, true > BitStream32BEMSB
32-bit big-endian data, MSB to LSB.
Definition: bitstream.h:266
A template implementing a bit stream for different data memory layouts.
Definition: bitstream.h:85
BitStreamImpl< 64, false, false > BitStream64BELSB
64-bit big-endian data, LSB to MSB.
Definition: bitstream.h:277
BitStreamImpl< 64, false, true > BitStream64BEMSB
64-bit big-endian data, MSB to LSB.
Definition: bitstream.h:275
Interface for a seekable & readable data stream.
Definition: readstream.h:265
A bit stream.
Definition: bitstream.h:40
virtual size_t size() const =0
Return the stream size in bits.
BitStreamImpl< 64, true, false > BitStream64LELSB
64-bit little-endian data, LSB to MSB.
Definition: bitstream.h:273
BitStreamImpl< 8, false, true > BitStream8MSB
8-bit data, MSB to LSB.
Definition: bitstream.h:248