1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-26 04:00:49 +01:00
GPXSee/src/map/IMG/subfile.cpp

143 lines
2.7 KiB
C++
Raw Normal View History

2021-02-03 22:16:00 +01:00
#include <cstring>
2021-04-10 15:27:40 +02:00
#include "imgdata.h"
2019-05-10 18:56:19 +02:00
#include "subfile.h"
2021-04-10 15:27:40 +02:00
using namespace IMG;
#define mod2n(x, m) ((x) & ((m) - 1));
2019-05-10 18:56:19 +02:00
bool SubFile::seek(Handle &handle, quint32 pos) const
{
2021-01-27 21:18:06 +01:00
if (_img) {
quint32 blockBits = _img->blockBits();
int blockNum = pos >> blockBits;
2020-02-09 23:24:48 +01:00
if (handle._blockNum != blockNum) {
2021-01-27 21:18:06 +01:00
if (blockNum >= _blocks->size())
2020-02-09 23:24:48 +01:00
return false;
2021-01-27 21:18:06 +01:00
if (!_img->readBlock(handle._file, _blocks->at(blockNum),
handle._data.data()))
2020-02-09 23:24:48 +01:00
return false;
handle._blockNum = blockNum;
}
2021-01-27 21:18:06 +01:00
handle._blockPos = mod2n(pos, 1U<<blockBits);
2020-02-09 23:24:48 +01:00
handle._pos = pos;
} else {
2021-01-27 21:18:06 +01:00
int blockNum = pos >> BLOCK_BITS;
2020-02-09 23:24:48 +01:00
if (handle._blockNum != blockNum) {
2021-01-27 21:18:06 +01:00
if (!handle._file.seek((quint64)blockNum << BLOCK_BITS))
return false;
2021-01-27 21:18:06 +01:00
if (handle._file.read(handle._data.data(), (1<<BLOCK_BITS)) < 0)
return false;
2020-02-09 23:24:48 +01:00
handle._blockNum = blockNum;
}
2019-05-10 18:56:19 +02:00
2021-01-27 21:18:06 +01:00
handle._blockPos = mod2n(pos, 1U<<BLOCK_BITS);
2020-02-09 23:24:48 +01:00
handle._pos = pos;
}
2021-01-27 21:18:06 +01:00
return true;
2019-05-10 18:56:19 +02:00
}
bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
{
quint8 bytes, shift, b;
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &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);
for (int i = 1; i <= bytes; i++) {
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &b))
return false;
val |= (((quint32)b) << (i * 8)) >> (8 - shift);
}
return true;
}
bool SubFile::readVUInt32(Handle &hdl, quint32 bytes, quint32 &val) const
{
switch (bytes) {
case 1:
return readUInt8(hdl, val);
case 2:
return readUInt16(hdl, val);
case 3:
return readUInt24(hdl, val);
case 4:
return readUInt32(hdl, val);
default:
return false;
}
}
bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
{
quint8 bits;
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &bits))
return false;
if (!(bits & 1)) {
2020-02-09 23:24:48 +01:00
seek(hdl, hdl._pos - 1);
if (!((bits>>1) & 1)) {
if (!((bits>>2) & 1)) {
if (!readUInt32(hdl, bitfield))
return false;
} else {
if (!readUInt24(hdl, bitfield))
return false;
}
bitfield >>= 3;
} else {
if (!readUInt16(hdl, bitfield))
return false;
bitfield >>= 2;
}
} else
bitfield = bits>>1;
return true;
}
2021-02-03 22:16:00 +01:00
2021-02-03 22:56:30 +01:00
bool SubFile::read(Handle &handle, char *buff, quint32 size) const
2021-02-03 22:16:00 +01:00
{
while (size) {
quint32 remaining = handle._data.size() - handle._blockPos;
if (size < remaining) {
memcpy(buff, handle._data.constData() + handle._blockPos, size);
handle._blockPos += size;
2021-02-03 22:49:06 +01:00
handle._pos += size;
2021-02-03 22:16:00 +01:00
return true;
} else {
memcpy(buff, handle._data.constData() + handle._blockPos,
remaining);
buff += remaining;
size -= remaining;
handle._blockPos = 0;
handle._pos += remaining;
if (!seek(handle, handle._pos))
return false;
}
}
return true;
}