#include "chunkstream.h" void ChunkStream::setSource(const QByteArray & data) { stream_.setVersion(QDataStream::Qt_4_8); data_ = const_cast(&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); } }