aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/bitstream.h172
-rw-r--r--test/common/bitstream.h118
2 files changed, 262 insertions, 28 deletions
diff --git a/common/bitstream.h b/common/bitstream.h
index c5226d5124..e867d86ea7 100644
--- a/common/bitstream.h
+++ b/common/bitstream.h
@@ -269,6 +269,152 @@ public:
}
};
+
+
+/**
+ * A cut-down version of MemoryReadStream specifically for use with BitStream.
+ * It removes the virtual call overhead for reading bytes from a memory buffer,
+ * and allows directly inlining this access.
+ *
+ * The code duplication with MemoryReadStream is not ideal.
+ * It might be possible to avoid this by making this a final subclass of
+ * MemoryReadStream, but that is a C++11 feature.
+ */
+class BitStreamMemoryStream {
+private:
+ const byte * const _ptrOrig;
+ const byte *_ptr;
+ const uint32 _size;
+ uint32 _pos;
+ DisposeAfterUse::Flag _disposeMemory;
+ bool _eos;
+
+public:
+ BitStreamMemoryStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
+ _ptrOrig(dataPtr),
+ _ptr(dataPtr),
+ _size(dataSize),
+ _pos(0),
+ _disposeMemory(disposeMemory),
+ _eos(false) {}
+
+ ~BitStreamMemoryStream() {
+ if (_disposeMemory)
+ free(const_cast<byte *>(_ptrOrig));
+ }
+
+ bool eos() const {
+ return _eos;
+ }
+
+ bool err() const {
+ return false;
+ }
+
+ int32 pos() const {
+ return _pos;
+ }
+
+ int32 size() const {
+ return _size;
+ }
+
+ bool seek(uint32 offset) {
+ assert(offset <= _size);
+
+ _eos = false;
+ _pos = offset;
+ _ptr = _ptrOrig + _pos;
+ return true;
+ }
+
+ byte readByte() {
+ if (_pos >= _size) {
+ _eos = true;
+ return 0;
+ }
+
+ _pos++;
+ return *_ptr++;
+ }
+
+ uint16 readUint16LE() {
+ if (_pos + 2 > _size) {
+ _eos = true;
+ if (_pos < _size) {
+ _pos++;
+ return *_ptr++;
+ } else {
+ return 0;
+ }
+ }
+
+ uint16 val = READ_LE_UINT16(_ptr);
+
+ _pos += 2;
+ _ptr += 2;
+
+ return val;
+ }
+
+ uint16 readUint16BE() {
+ if (_pos + 2 > _size) {
+ _eos = true;
+ if (_pos < _size) {
+ _pos++;
+ return (*_ptr++) << 8;
+ } else {
+ return 0;
+ }
+ }
+
+ uint16 val = READ_LE_UINT16(_ptr);
+
+ _pos += 2;
+ _ptr += 2;
+
+ return val;
+ }
+
+ uint32 readUint32LE() {
+ if (_pos + 4 > _size) {
+ uint32 val = readByte();
+ val |= (uint32)readByte() << 8;
+ val |= (uint32)readByte() << 16;
+ val |= (uint32)readByte() << 24;
+
+ return val;
+ }
+
+ uint32 val = READ_LE_UINT32(_ptr);
+
+ _pos += 4;
+ _ptr += 4;
+
+ return val;
+ }
+
+ uint32 readUint32BE() {
+ if (_pos + 4 > _size) {
+ uint32 val = (uint32)readByte() << 24;
+ val |= (uint32)readByte() << 16;
+ val |= (uint32)readByte() << 8;
+ val |= (uint32)readByte();
+
+ return val;
+ }
+
+ uint32 val = READ_BE_UINT32(_ptr);
+
+ _pos += 4;
+ _ptr += 4;
+
+ return val;
+ }
+
+};
+
+
// typedefs for various memory layouts.
/** 8-bit data, MSB to LSB. */
@@ -294,6 +440,32 @@ typedef BitStreamImpl<SeekableReadStream, 32, false, true > BitStream32BEMSB;
/** 32-bit big-endian data, LSB to MSB. */
typedef BitStreamImpl<SeekableReadStream, 32, false, false> BitStream32BELSB;
+
+
+/** 8-bit data, MSB to LSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 8, false, true > BitStreamMemory8MSB;
+/** 8-bit data, LSB to MSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 8, false, false> BitStreamMemory8LSB;
+
+/** 16-bit little-endian data, MSB to LSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 16, true , true > BitStreamMemory16LEMSB;
+/** 16-bit little-endian data, LSB to MSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 16, true , false> BitStreamMemory16LELSB;
+/** 16-bit big-endian data, MSB to LSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 16, false, true > BitStreamMemory16BEMSB;
+/** 16-bit big-endian data, LSB to MSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 16, false, false> BitStreamMemory16BELSB;
+
+/** 32-bit little-endian data, MSB to LSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 32, true , true > BitStreamMemory32LEMSB;
+/** 32-bit little-endian data, LSB to MSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 32, true , false> BitStreamMemory32LELSB;
+/** 32-bit big-endian data, MSB to LSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 32, false, true > BitStreamMemory32BEMSB;
+/** 32-bit big-endian data, LSB to MSB. */
+typedef BitStreamImpl<BitStreamMemoryStream, 32, false, false> BitStreamMemory32BELSB;
+
+
} // End of namespace Common
#endif // COMMON_BITSTREAM_H
diff --git a/test/common/bitstream.h b/test/common/bitstream.h
index 3f6a15fcd8..0488169183 100644
--- a/test/common/bitstream.h
+++ b/test/common/bitstream.h
@@ -5,13 +5,14 @@
class BitStreamTestSuite : public CxxTest::TestSuite
{
- public:
- void test_get_bit() {
+private:
+ template<class MS, class BS>
+ void tmpl_get_bit() {
byte contents[] = { 'a' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8MSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
TS_ASSERT_EQUALS(bs.getBit(), 0u);
TS_ASSERT_EQUALS(bs.getBit(), 1u);
@@ -19,13 +20,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.pos(), 3u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_get_bit() {
+ tmpl_get_bit<Common::MemoryReadStream, Common::BitStream8MSB>();
+ tmpl_get_bit<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
+ }
- void test_get_bits() {
+private:
+ template<class MS, class BS>
+ void tmpl_get_bits() {
byte contents[] = { 'a', 'b' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8MSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
TS_ASSERT_EQUALS(bs.getBits(3), 3u);
TS_ASSERT_EQUALS(bs.pos(), 3u);
@@ -33,13 +41,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.pos(), 11u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_get_bits() {
+ tmpl_get_bits<Common::MemoryReadStream, Common::BitStream8MSB>();
+ tmpl_get_bits<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
+ }
- void test_skip() {
+private:
+ template<class MS, class BS>
+ void tmpl_skip() {
byte contents[] = { 'a', 'b' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8MSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
bs.skip(5);
TS_ASSERT_EQUALS(bs.pos(), 5u);
@@ -48,13 +63,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.getBits(3), 6u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_skip() {
+ tmpl_skip<Common::MemoryReadStream, Common::BitStream8MSB>();
+ tmpl_skip<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
+ }
- void test_rewind() {
+private:
+ template<class MS, class BS>
+ void tmpl_rewind() {
byte contents[] = { 'a' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8MSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
bs.skip(5);
TS_ASSERT_EQUALS(bs.pos(), 5u);
@@ -65,13 +87,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.size(), 8u);
}
+public:
+ void test_rewind() {
+ tmpl_rewind<Common::MemoryReadStream, Common::BitStream8MSB>();
+ tmpl_rewind<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
+ }
- void test_peek_bit() {
+private:
+ template<class MS, class BS>
+ void tmpl_peek_bit() {
byte contents[] = { 'a' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8MSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
TS_ASSERT_EQUALS(bs.peekBit(), 0u);
TS_ASSERT_EQUALS(bs.pos(), 0u);
@@ -81,13 +110,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.pos(), 1u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_peek_bit() {
+ tmpl_peek_bit<Common::MemoryReadStream, Common::BitStream8MSB>();
+ tmpl_peek_bit<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
+ }
- void test_peek_bits() {
+private:
+ template<class MS, class BS>
+ void tmpl_peek_bits() {
byte contents[] = { 'a', 'b' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8MSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
TS_ASSERT_EQUALS(bs.peekBits(3), 3u);
TS_ASSERT_EQUALS(bs.pos(), 0u);
@@ -100,13 +136,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.peekBits(5), 2u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_peek_bits() {
+ tmpl_peek_bits<Common::MemoryReadStream, Common::BitStream8MSB>();
+ tmpl_peek_bits<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
+ }
- void test_eos() {
+private:
+ template<class MS, class BS>
+ void tmpl_eos() {
byte contents[] = { 'a', 'b' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8MSB bs(ms);
+ BS bs(ms);
bs.skip(11);
TS_ASSERT_EQUALS(bs.pos(), 11u);
TS_ASSERT_EQUALS(bs.getBits(5), 2u);
@@ -116,13 +159,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.pos(), 0u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_eos() {
+ tmpl_eos<Common::MemoryReadStream, Common::BitStream8MSB>();
+ tmpl_eos<Common::BitStreamMemoryStream, Common::BitStreamMemory8MSB>();
+ }
- void test_get_bits_lsb() {
+private:
+ template<class MS, class BS>
+ void tmpl_get_bits_lsb() {
byte contents[] = { 'a', 'b' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8LSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
TS_ASSERT_EQUALS(bs.getBits(3), 1u);
TS_ASSERT_EQUALS(bs.pos(), 3u);
@@ -130,13 +180,20 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.pos(), 11u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_get_bits_lsb() {
+ tmpl_get_bits_lsb<Common::MemoryReadStream, Common::BitStream8LSB>();
+ tmpl_get_bits_lsb<Common::BitStreamMemoryStream, Common::BitStreamMemory8LSB>();
+ }
- void test_peek_bits_lsb() {
+private:
+ template<class MS, class BS>
+ void tmpl_peek_bits_lsb() {
byte contents[] = { 'a', 'b' };
- Common::MemoryReadStream ms(contents, sizeof(contents));
+ MS ms(contents, sizeof(contents));
- Common::BitStream8LSB bs(ms);
+ BS bs(ms);
TS_ASSERT_EQUALS(bs.pos(), 0u);
TS_ASSERT_EQUALS(bs.peekBits(3), 1u);
TS_ASSERT_EQUALS(bs.pos(), 0u);
@@ -149,4 +206,9 @@ class BitStreamTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(bs.peekBits(5), 12u);
TS_ASSERT(!bs.eos());
}
+public:
+ void test_peek_bits_lsb() {
+ tmpl_peek_bits_lsb<Common::MemoryReadStream, Common::BitStream8LSB>();
+ tmpl_peek_bits_lsb<Common::BitStreamMemoryStream, Common::BitStreamMemory8LSB>();
+ }
};