mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-04-12 00:29:11 +02:00
221 lines
3.6 KiB
C++
221 lines
3.6 KiB
C++
#include "bitstream.h"
|
|
|
|
using namespace Garmin;
|
|
using namespace IMG;
|
|
|
|
bool BitStream1::flush()
|
|
{
|
|
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
|
|
return false;
|
|
|
|
_length = 0;
|
|
_remaining = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BitStream1::readUInt24(quint32 &val)
|
|
{
|
|
quint8 b;
|
|
|
|
val = 0;
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
if (!read(8, b))
|
|
return false;
|
|
val |= (b << (i << 3));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool BitStream4F::flush()
|
|
{
|
|
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
|
|
return false;
|
|
|
|
_length = 0;
|
|
_used = 32;
|
|
_unused = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BitStream4F::read(quint32 bits, quint32 &val)
|
|
{
|
|
if (bits <= available()) {
|
|
val = bits ? (_data << _used) >> (32U - bits) : 0;
|
|
_used += bits;
|
|
return true;
|
|
}
|
|
|
|
Q_ASSERT(_length && !_unused);
|
|
quint32 old = (_used < 32U) ? (_data << _used) >> (32U - bits) : 0;
|
|
quint32 bytes = qMin(_length, 4U);
|
|
|
|
if (!_file.readVUInt32SW(_hdl, bytes, _data))
|
|
return false;
|
|
|
|
_used -= 32U - bits;
|
|
_length -= bytes;
|
|
_unused = (4U - bytes) << 3;
|
|
_data <<= _unused;
|
|
|
|
val = _data >> (32 - _used) | old;
|
|
|
|
return true;
|
|
}
|
|
|
|
BitStream4R::BitStream4R(const SubFile &file, SubFile::Handle &hdl,
|
|
quint32 length) : BitStream4(file, hdl, length)
|
|
{
|
|
_file.seek(_hdl, _file.pos(_hdl) - 4);
|
|
}
|
|
|
|
bool BitStream4R::readBytes(quint32 bytes, quint32 &val)
|
|
{
|
|
quint32 b;
|
|
|
|
val = 0;
|
|
for (quint32 i = 0; i < bytes; i++) {
|
|
if (!read(8, b))
|
|
return false;
|
|
val |= (b << (i << 3));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BitStream4R::readBytesAligned(quint32 bytes, quint32 &val)
|
|
{
|
|
quint32 bits = _used & 7U;
|
|
quint32 b;
|
|
|
|
if (bits && !read(8U - bits, b))
|
|
return false;
|
|
|
|
return readBytes(bytes, val);
|
|
}
|
|
|
|
bool BitStream4R::readVUInt32(quint32 &val)
|
|
{
|
|
quint32 b;
|
|
quint8 bytes, shift;
|
|
|
|
if (!readBytesAligned(1, b))
|
|
return false;
|
|
|
|
if ((b & 1) == 0) {
|
|
if ((b & 2) == 0) {
|
|
bytes = ((b >> 2) & 1) ^ 3;
|
|
shift = 5;
|
|
} else {
|
|
shift = 6;
|
|
bytes = 1;
|
|
}
|
|
} else {
|
|
shift = 7;
|
|
bytes = 0;
|
|
}
|
|
|
|
val = b >> (8 - shift);
|
|
|
|
if (bytes) {
|
|
if (!readBytes(bytes, b))
|
|
return false;
|
|
val = val | (b << shift);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BitStream4R::readVUint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits)
|
|
{
|
|
quint32 b, eb;
|
|
|
|
if (!readBytesAligned(1, b))
|
|
return false;
|
|
|
|
if (!(b & 1)) {
|
|
val1 = b >> 3;
|
|
val2 = b >> 1 & 3;
|
|
val2Bits = 2;
|
|
} else {
|
|
eb = b & 2;
|
|
val2 = b >> 2 & 0x3f;
|
|
val2Bits = eb * 2 + 6;
|
|
if (!readBytes((eb >> 1 | 2) - 1, b))
|
|
return false;
|
|
if (eb) {
|
|
val2 = val2 | (b & 0xf) << 6;
|
|
b = b >> 4 & 0xfff;
|
|
}
|
|
val1 = b;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BitStream4R::skip(quint32 bytes)
|
|
{
|
|
quint32 ab = available() >> 3;
|
|
|
|
if (bytes <= ab)
|
|
_used += bytes << 3;
|
|
else {
|
|
if (bytes > ab + _length)
|
|
return false;
|
|
|
|
quint32 seek = (bytes - ab) & 0xFFFFFFFC;
|
|
quint32 read = (bytes - ab) & 3U;
|
|
if (seek && !_file.seek(_hdl, _file.pos(_hdl) - seek))
|
|
return false;
|
|
_length -= seek;
|
|
if (read) {
|
|
quint32 rb = qMin(_length, 4U);
|
|
if (!_file.readUInt32(_hdl, _data))
|
|
return false;
|
|
if (!_file.seek(_hdl, _file.pos(_hdl) - 8U))
|
|
return false;
|
|
_length -= rb;
|
|
_unused = (4U - rb) << 3;
|
|
_used = read << 3;
|
|
} else
|
|
_used = 32U;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void BitStream4R::resize(quint32 bytes)
|
|
{
|
|
quint32 ab = bs(available());
|
|
|
|
if (ab <= bytes)
|
|
_length = bytes - ab;
|
|
else {
|
|
_length = 0;
|
|
_unused += (ab - bytes) << 3;
|
|
}
|
|
}
|
|
|
|
void BitStream4R::save(State &state)
|
|
{
|
|
state.pos = _file.pos(_hdl);
|
|
state.length = _length;
|
|
state.used = _used;
|
|
state.unused = _unused;
|
|
state.data = _data;
|
|
}
|
|
|
|
bool BitStream4R::restore(const State &state)
|
|
{
|
|
_length = state.length;
|
|
_used = state.used;
|
|
_unused = state.unused;
|
|
_data = state.data;
|
|
|
|
return _file.seek(_hdl, state.pos);
|
|
}
|