/* QAD - Qt ADvanced Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef CHUNKSTREAM_H #define CHUNKSTREAM_H #include #include #include #include #include "qad_utils_export.h" class QAD_UTILS_EXPORT ChunkStream { public: enum Version { Version_1 /*! First, old version */, Version_2 /*! Second, more optimized version */ = 2, }; ChunkStream(const QByteArray & data): version_(Version_2) {setSource(data);} ChunkStream(QDataStream & str): version_(Version_2) {setSource(str);} ChunkStream(QByteArray * data = 0, Version v = Version_2): version_(v) {setSource(data);} ChunkStream(Version v): version_(v) {setSource(0);} ~ChunkStream(); template struct Chunk { Chunk(int i, const T & d): id(i), data(d) {} int id; T data; }; template struct ChunkConst { ChunkConst(int i, const T & d): id(i), data(d) {} int id; const T & data; }; template static ChunkConst chunk(int id, const T & data) {return ChunkConst(id, data);} template ChunkStream & add(int id, const T & data) {*this << ChunkConst(id, data); return *this;} void setSource(const QByteArray & data); void setSource(QDataStream & str); void setSource(QByteArray * data); QDataStream & dataStream() {return stream_;} QByteArray data() const {return tmp_data;} bool atEnd() const {return stream_.atEnd();} Version version() const {return (Version)version_;} int read(); void readAll(); int getID() {return last_id;} template T getData() const {T ret; QDataStream s(last_data); s.setVersion(QDataStream::Qt_4_8); s >> ret; return ret;} template void get(T & v) const {v = getData();} template const ChunkStream & get(int id, T & v) const { QByteArray ba = data_map.value(id); if (!ba.isEmpty()) { QDataStream s(ba); s.setVersion(QDataStream::Qt_4_8); s >> v; } return *this; } private: void _init(); static uint readVInt(QDataStream & s); static void writeVInt(QDataStream & s, uint val); int last_id; uchar version_; QByteArray * data_, last_data, tmp_data; QBuffer buffer; QDataStream stream_; QMap data_map; template friend ChunkStream & operator <<(ChunkStream & s, const ChunkStream::Chunk & c); template friend ChunkStream & operator <<(ChunkStream & s, const ChunkStream::ChunkConst & c); }; template ChunkStream & operator <<(ChunkStream & s, const ChunkStream::Chunk & c) { QByteArray ba; QDataStream bas(&ba, QIODevice::WriteOnly); bas.setVersion(QDataStream::Qt_4_8); bas << c.data; switch (s.version_) { case ChunkStream::Version_1: s.stream_ << c.id << ba; break; case ChunkStream::Version_2: if (s.data_->isEmpty()) s.stream_ << uchar(uchar(s.version_) | 0x80); ChunkStream::writeVInt(s.stream_, c.id); ChunkStream::writeVInt(s.stream_, ba.size()); s.stream_.writeRawData(ba.data(), ba.size()); break; default: break; } return s; } template ChunkStream & operator <<(ChunkStream & s, const ChunkStream::ChunkConst & c) { QByteArray ba; QDataStream bas(&ba, QIODevice::WriteOnly); bas.setVersion(QDataStream::Qt_4_8); bas << c.data; switch (s.version_) { case ChunkStream::Version_1: s.stream_ << c.id << ba; break; case ChunkStream::Version_2: if (s.data_->isEmpty()) s.stream_ << uchar(uchar(s.version_) | 0x80); ChunkStream::writeVInt(s.stream_, c.id); ChunkStream::writeVInt(s.stream_, ba.size()); s.stream_.writeRawData(ba.data(), ba.size()); break; default: break; } return s; } #endif // CHUNKSTREAM_H