mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-24 23:31:32 +08:00
Serialization
- Adds prototype impls for InMemoryWriter and InMemoryReader. - Use major- and minor-version idiom
This commit is contained in:
parent
6c587ff8c4
commit
4debaaaf85
@ -5,6 +5,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
#include <QBuffer>
|
||||||
|
|
||||||
#include "ads/API.h"
|
#include "ads/API.h"
|
||||||
|
|
||||||
@ -13,26 +14,32 @@ ADS_NAMESPACE_SER_BEGIN
|
|||||||
class Header
|
class Header
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static qint32 MAGIC;
|
||||||
|
static qint32 MAJOR_VERSION;
|
||||||
|
static qint32 MINOR_VERSION;
|
||||||
|
|
||||||
Header();
|
Header();
|
||||||
qint32 magic;
|
qint32 magic;
|
||||||
qint32 version;
|
qint32 majorVersion;
|
||||||
|
qint32 minorVersion;
|
||||||
};
|
};
|
||||||
QDataStream& operator<<(QDataStream& out, const Header& data);
|
QDataStream& operator<<(QDataStream& out, const Header& data);
|
||||||
QDataStream& operator>>(QDataStream& in, Header& data);
|
QDataStream& operator>>(QDataStream& in, Header& data);
|
||||||
|
|
||||||
|
|
||||||
class OffsetHeader
|
class OffsetsHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OffsetHeader();
|
OffsetsHeader();
|
||||||
qint64 length;
|
|
||||||
QList<class OffsetHeaderEntry> entries;
|
qint64 entriesCount;
|
||||||
|
QList<class OffsetsHeaderEntry> entries;
|
||||||
};
|
};
|
||||||
QDataStream& operator<<(QDataStream& out, const OffsetHeader& data);
|
QDataStream& operator<<(QDataStream& out, const OffsetsHeader& data);
|
||||||
QDataStream& operator>>(QDataStream& in, OffsetHeader& data);
|
QDataStream& operator>>(QDataStream& in, OffsetsHeader& data);
|
||||||
|
|
||||||
|
|
||||||
class OffsetHeaderEntry
|
class OffsetsHeaderEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type
|
enum Type
|
||||||
@ -42,13 +49,13 @@ public:
|
|||||||
SectionIndex = 0x00000003
|
SectionIndex = 0x00000003
|
||||||
};
|
};
|
||||||
|
|
||||||
OffsetHeaderEntry();
|
OffsetsHeaderEntry();
|
||||||
qint32 type;
|
qint32 type;
|
||||||
qint64 offset;
|
qint64 offset;
|
||||||
qint64 length;
|
qint64 contentSize;
|
||||||
};
|
};
|
||||||
QDataStream& operator<<(QDataStream& out, const OffsetHeaderEntry& data);
|
QDataStream& operator<<(QDataStream& out, const OffsetsHeaderEntry& data);
|
||||||
QDataStream& operator>>(QDataStream& in, OffsetHeaderEntry& data);
|
QDataStream& operator>>(QDataStream& in, OffsetsHeaderEntry& data);
|
||||||
|
|
||||||
|
|
||||||
class Section
|
class Section
|
||||||
@ -111,6 +118,42 @@ public:
|
|||||||
qint32 sectionsCount;
|
qint32 sectionsCount;
|
||||||
QList<Section> sections;
|
QList<Section> sections;
|
||||||
};
|
};
|
||||||
|
QDataStream& operator<<(QDataStream& out, const SectionIndexData& data);
|
||||||
|
QDataStream& operator>>(QDataStream& in, SectionIndexData& data);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The InMemoryWriter class writes into a QByteArray.
|
||||||
|
*/
|
||||||
|
class InMemoryWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InMemoryWriter();
|
||||||
|
bool write(OffsetsHeaderEntry::Type type, const QByteArray& data);
|
||||||
|
bool write(const SectionIndexData& data);
|
||||||
|
QByteArray toByteArray() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QBuffer _contentBuffer;
|
||||||
|
OffsetsHeader _offsetsHeader;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The InMemoryReader class
|
||||||
|
*/
|
||||||
|
class InMemoryReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InMemoryReader(const QByteArray& data);
|
||||||
|
bool initReadHeader();
|
||||||
|
bool read(OffsetsHeaderEntry::Type type, QByteArray &data) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray _data;
|
||||||
|
QBuffer _buff;
|
||||||
|
|
||||||
|
OffsetsHeader _offsetsHeader;
|
||||||
|
};
|
||||||
|
|
||||||
ADS_NAMESPACE_SER_END
|
ADS_NAMESPACE_SER_END
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "ads/Serialization.h"
|
#include "ads/Serialization.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
ADS_NAMESPACE_SER_BEGIN
|
ADS_NAMESPACE_SER_BEGIN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -11,7 +13,8 @@ ADS_NAMESPACE_SER_BEGIN
|
|||||||
# Data Format Header
|
# Data Format Header
|
||||||
|
|
||||||
quint32 Magic
|
quint32 Magic
|
||||||
quint32 Version
|
quint32 Major Version
|
||||||
|
quint32 Minor Version
|
||||||
|
|
||||||
# Offsets of available contents
|
# Offsets of available contents
|
||||||
|
|
||||||
@ -58,48 +61,54 @@ ADS_NAMESPACE_SER_BEGIN
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
qint32 Header::MAGIC = 0x00001337;
|
||||||
|
qint32 Header::MAJOR_VERSION = 2;
|
||||||
|
qint32 Header::MINOR_VERSION = 0;
|
||||||
|
|
||||||
Header::Header() :
|
Header::Header() :
|
||||||
magic(0), version(0)
|
magic(0), majorVersion(0), minorVersion(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& out, const Header& data)
|
QDataStream& operator<<(QDataStream& out, const Header& data)
|
||||||
{
|
{
|
||||||
out << data.magic;
|
out << data.magic;
|
||||||
out << data.version;
|
out << data.majorVersion;
|
||||||
|
out << data.minorVersion;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator>>(QDataStream& in, Header& data)
|
QDataStream& operator>>(QDataStream& in, Header& data)
|
||||||
{
|
{
|
||||||
in >> data.magic;
|
in >> data.magic;
|
||||||
in >> data.version;
|
in >> data.majorVersion;
|
||||||
|
in >> data.minorVersion;
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
OffsetHeader::OffsetHeader() :
|
OffsetsHeader::OffsetsHeader() :
|
||||||
length(0)
|
entriesCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& out, const OffsetHeader& data)
|
QDataStream& operator<<(QDataStream& out, const OffsetsHeader& data)
|
||||||
{
|
{
|
||||||
out << data.length;
|
out << data.entriesCount;
|
||||||
for (int i = 0; i < data.length; ++i)
|
for (int i = 0; i < data.entriesCount; ++i)
|
||||||
{
|
{
|
||||||
out << data.entries.at(i);
|
out << data.entries.at(i);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator>>(QDataStream& in, OffsetHeader& data)
|
QDataStream& operator>>(QDataStream& in, OffsetsHeader& data)
|
||||||
{
|
{
|
||||||
in >> data.length;
|
in >> data.entriesCount;
|
||||||
for (int i = 0; i < data.length; ++i)
|
for (int i = 0; i < data.entriesCount; ++i)
|
||||||
{
|
{
|
||||||
OffsetHeaderEntry entry;
|
OffsetsHeaderEntry entry;
|
||||||
in >> entry;
|
in >> entry;
|
||||||
data.entries.append(entry);
|
data.entries.append(entry);
|
||||||
}
|
}
|
||||||
@ -108,24 +117,24 @@ QDataStream& operator>>(QDataStream& in, OffsetHeader& data)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
OffsetHeaderEntry::OffsetHeaderEntry() :
|
OffsetsHeaderEntry::OffsetsHeaderEntry() :
|
||||||
type(Unknown), offset(0), length(0)
|
type(Unknown), offset(0), contentSize(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& out, const OffsetHeaderEntry& data)
|
QDataStream& operator<<(QDataStream& out, const OffsetsHeaderEntry& data)
|
||||||
{
|
{
|
||||||
out << data.type;
|
out << data.type;
|
||||||
out << data.offset;
|
out << data.offset;
|
||||||
out << data.length;
|
out << data.contentSize;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator>>(QDataStream& in, OffsetHeaderEntry& data)
|
QDataStream& operator>>(QDataStream& in, OffsetsHeaderEntry& data)
|
||||||
{
|
{
|
||||||
in >> data.type;
|
in >> data.type;
|
||||||
in >> data.offset;
|
in >> data.offset;
|
||||||
in >> data.length;
|
in >> data.contentSize;
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,4 +245,172 @@ QDataStream& operator>>(QDataStream& in, HierarchyData& data)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SectionIndexData::SectionIndexData() :
|
||||||
|
sectionsCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream& operator<<(QDataStream& out, const SectionIndexData& data)
|
||||||
|
{
|
||||||
|
out << data.sectionsCount;
|
||||||
|
for (int i = 0; i < data.sectionsCount; ++i)
|
||||||
|
{
|
||||||
|
out << data.sections.at(i);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream& operator>>(QDataStream& in, SectionIndexData& data)
|
||||||
|
{
|
||||||
|
in >> data.sectionsCount;
|
||||||
|
for (int i = 0; i < data.sectionsCount; ++i)
|
||||||
|
{
|
||||||
|
Section s;
|
||||||
|
in >> s;
|
||||||
|
data.sections.append(s);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
InMemoryWriter::InMemoryWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryWriter::write(OffsetsHeaderEntry::Type type, const QByteArray& data)
|
||||||
|
{
|
||||||
|
OffsetsHeaderEntry entry;
|
||||||
|
entry.type = type;
|
||||||
|
entry.offset = _contentBuffer.pos(); // Relative offset!
|
||||||
|
entry.contentSize = data.size();
|
||||||
|
|
||||||
|
_contentBuffer.write(data);
|
||||||
|
|
||||||
|
_offsetsHeader.entries.append(entry);
|
||||||
|
_offsetsHeader.entriesCount += 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryWriter::write(const SectionIndexData& data)
|
||||||
|
{
|
||||||
|
OffsetsHeaderEntry entry;
|
||||||
|
entry.type = OffsetsHeaderEntry::SectionIndex;
|
||||||
|
entry.offset = _contentBuffer.pos(); // Relative offset!
|
||||||
|
|
||||||
|
QDataStream out(&_contentBuffer);
|
||||||
|
out.setVersion(QDataStream::Qt_4_5);
|
||||||
|
out << data;
|
||||||
|
|
||||||
|
entry.contentSize = _contentBuffer.size() - entry.offset;
|
||||||
|
|
||||||
|
_offsetsHeader.entries.append(entry);
|
||||||
|
_offsetsHeader.entriesCount += 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray InMemoryWriter::toByteArray() const
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
QBuffer buff(&data);
|
||||||
|
|
||||||
|
QDataStream out(&buff);
|
||||||
|
out.setVersion(QDataStream::Qt_4_5);
|
||||||
|
|
||||||
|
// Basic format header.
|
||||||
|
Header header;
|
||||||
|
header.magic = Header::MAGIC;
|
||||||
|
header.majorVersion = Header::MAJOR_VERSION;
|
||||||
|
header.minorVersion = Header::MINOR_VERSION;
|
||||||
|
out << header;
|
||||||
|
|
||||||
|
// Offsets-Header
|
||||||
|
// - Save begin pos
|
||||||
|
// - Write OffsetsHeader
|
||||||
|
// - Convert relative- to absolute-offsets
|
||||||
|
// - Seek back to begin-pos and write OffsetsHeader again.
|
||||||
|
// Use a copy of OffsetsHeader to keep the _offsetsHeader relative.
|
||||||
|
const qint64 posOffsetHeaders = buff.pos();
|
||||||
|
OffsetsHeader offsetsHeader = _offsetsHeader;
|
||||||
|
out << offsetsHeader;
|
||||||
|
|
||||||
|
// Now we know the size of the entire header.
|
||||||
|
// We can update the relative- to absolute-offsets now.
|
||||||
|
const qint64 allHeaderSize = buff.pos();
|
||||||
|
for (int i = 0; i < offsetsHeader.entriesCount; ++i)
|
||||||
|
{
|
||||||
|
offsetsHeader.entries[i].offset += allHeaderSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek back and write again with absolute offsets.
|
||||||
|
// TODO Thats not nice, but it works...
|
||||||
|
buff.seek(posOffsetHeaders);
|
||||||
|
out << offsetsHeader;
|
||||||
|
|
||||||
|
// Write contents.
|
||||||
|
buff.write(_contentBuffer.data());
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
InMemoryReader::InMemoryReader(const QByteArray& data) :
|
||||||
|
_data(data), _buff(&_data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryReader::initReadHeader()
|
||||||
|
{
|
||||||
|
QDataStream in(&_buff);
|
||||||
|
in.setVersion(QDataStream::Qt_4_5);
|
||||||
|
|
||||||
|
// Basic format header.
|
||||||
|
Header header;
|
||||||
|
in >> header;
|
||||||
|
if (header.magic != Header::MAGIC)
|
||||||
|
{
|
||||||
|
qWarning() << QString("invalid format (magic=%1)").arg(header.magic);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (header.majorVersion > Header::MAJOR_VERSION)
|
||||||
|
{
|
||||||
|
qWarning() << QString("format is too new (major=%1; minor=%2)")
|
||||||
|
.arg(header.majorVersion).arg(header.minorVersion);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OffsetsHeader.
|
||||||
|
in >> _offsetsHeader;
|
||||||
|
|
||||||
|
return !in.atEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryReader::read(OffsetsHeaderEntry::Type type, QByteArray& data) const
|
||||||
|
{
|
||||||
|
// Find offset for "type".
|
||||||
|
int index = -1;
|
||||||
|
for (int i = 0; i < _offsetsHeader.entriesCount; ++i)
|
||||||
|
{
|
||||||
|
if (_offsetsHeader.entries.at(index).type == type)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index < 0)
|
||||||
|
return false;
|
||||||
|
else if (_offsetsHeader.entries.at(index).offset == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const OffsetsHeaderEntry& entry = _offsetsHeader.entries.at(index);
|
||||||
|
_buff.seek(entry.offset);
|
||||||
|
data.append(_buff.read(entry.contentSize));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ADS_NAMESPACE_SER_END
|
ADS_NAMESPACE_SER_END
|
||||||
|
Loading…
Reference in New Issue
Block a user