118 lines
2.5 KiB
C++
118 lines
2.5 KiB
C++
#include "chunkstream.h"
|
|
|
|
|
|
void ChunkStream::setSource(const QByteArray & data) {
|
|
stream_.setVersion(QDataStream::Qt_4_8);
|
|
data_ = const_cast<QByteArray *>(&data);
|
|
_init();
|
|
}
|
|
|
|
|
|
void ChunkStream::setSource(QByteArray * data) {
|
|
stream_.setVersion(QDataStream::Qt_4_8);
|
|
data_ = (data ? data : &tmp_data);
|
|
_init();
|
|
}
|
|
|
|
|
|
void ChunkStream::setSource(QDataStream & str) {
|
|
stream_.setVersion(QDataStream::Qt_4_8);
|
|
str >> tmp_data;
|
|
data_ = &tmp_data;
|
|
_init();
|
|
}
|
|
|
|
|
|
int ChunkStream::read() {
|
|
switch (version_) {
|
|
case Version_1: stream_ >> last_id >> last_data; break;
|
|
case Version_2:
|
|
last_id = readVInt(stream_);
|
|
last_data.resize(readVInt(stream_));
|
|
// piCout << last_id << last_data.size();
|
|
stream_.readRawData(last_data.data(), last_data.size());
|
|
break;
|
|
default: break;
|
|
}
|
|
return last_id;
|
|
}
|
|
|
|
|
|
void ChunkStream::readAll() {
|
|
data_map.clear();
|
|
while (!atEnd()) {
|
|
read();
|
|
data_map[last_id] = last_data;
|
|
}
|
|
}
|
|
|
|
|
|
ChunkStream::~ChunkStream() {}
|
|
|
|
|
|
void ChunkStream::_init() {
|
|
last_id = -1;
|
|
last_data.clear();
|
|
buffer.close();
|
|
buffer.setBuffer(data_);
|
|
buffer.open(QIODevice::ReadWrite);
|
|
stream_.setDevice(&buffer);
|
|
if (!data_->isEmpty()) {
|
|
uchar v = data_->at(0);
|
|
if ((v & 0x80) == 0x80) {
|
|
v &= 0x7f;
|
|
switch (v) {
|
|
case 2:
|
|
version_ = (uchar)Version_2;
|
|
stream_.skipRawData(1);
|
|
break;
|
|
default: version_ = Version_1; break;
|
|
}
|
|
} else
|
|
version_ = Version_1;
|
|
}
|
|
}
|
|
|
|
|
|
uint ChunkStream::readVInt(QDataStream & s) {
|
|
if (s.atEnd()) return 0;
|
|
uchar bytes[4];
|
|
s >> bytes[0];
|
|
uchar abc = 0;
|
|
if (bytes[0] == 0xf0) {
|
|
abc = 3;
|
|
for (int i = 0; i < 4; ++i)
|
|
s >> bytes[i];
|
|
} else {
|
|
for (abc = 0; abc < 3; ++abc) {
|
|
uchar mask = (0x80 >> abc);
|
|
if ((bytes[0] & mask) == mask) {
|
|
// if (s.isEmpty()) return 0;
|
|
bytes[0] &= (mask - 1);
|
|
s >> bytes[abc + 1];
|
|
} else
|
|
break;
|
|
}
|
|
}
|
|
uint ret = 0;
|
|
for (int i = 0; i <= abc; ++i) {
|
|
ret += (bytes[i] << (8 * ((int)abc - i)));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
void ChunkStream::writeVInt(QDataStream & s, uint val) {
|
|
if (val <= 0x7f) {
|
|
s << uchar(val);
|
|
} else if (val <= 0x3fff) {
|
|
s << uchar((val >> 8) | 0x80) << uchar(val & 0xff);
|
|
} else if (val <= 0x1fffff) {
|
|
s << uchar((val >> 16) | 0xc0) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
|
} else if (val <= 0xfffffff) {
|
|
s << uchar((val >> 24) | 0xe0) << uchar((val >> 16) & 0xff) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
|
} else {
|
|
s << uchar(0xf0) << uchar((val >> 24) & 0xff) << uchar((val >> 16) & 0xff) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
|
}
|
|
}
|