mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-18 22:37:16 +02:00
More work on generic containers.
This commit is contained in:
parent
c045595ccb
commit
6260d661f3
2 changed files with 301 additions and 62 deletions
|
@ -45,7 +45,9 @@ static int metaObjectStreamer = Bitstream::registerTypeStreamer(qMetaTypeId<cons
|
|||
new SimpleTypeStreamer<const QMetaObject*>());
|
||||
|
||||
static int genericValueStreamer = Bitstream::registerTypeStreamer(
|
||||
qRegisterMetaType<GenericValue>(), new GenericTypeStreamer());
|
||||
qRegisterMetaType<GenericValue>(), new GenericValueStreamer());
|
||||
|
||||
static int qVariantPairListMetaTypeId = qRegisterMetaType<QVariantPairList>();
|
||||
|
||||
IDStreamer::IDStreamer(Bitstream& stream) :
|
||||
_stream(stream),
|
||||
|
@ -1173,65 +1175,10 @@ Bitstream& Bitstream::operator<(const TypeStreamer* streamer) {
|
|||
}
|
||||
const char* typeName = streamer->getName();
|
||||
*this << QByteArray::fromRawData(typeName, strlen(typeName));
|
||||
if (_metadataType == NO_METADATA) {
|
||||
return *this;
|
||||
}
|
||||
TypeStreamer::Category category = streamer->getCategory();
|
||||
*this << (int)category;
|
||||
switch (category) {
|
||||
case TypeStreamer::SIMPLE_CATEGORY:
|
||||
return *this;
|
||||
|
||||
case TypeStreamer::ENUM_CATEGORY: {
|
||||
QMetaEnum metaEnum = streamer->getMetaEnum();
|
||||
if (_metadataType == FULL_METADATA) {
|
||||
*this << metaEnum.keyCount();
|
||||
for (int i = 0; i < metaEnum.keyCount(); i++) {
|
||||
*this << QByteArray::fromRawData(metaEnum.key(i), strlen(metaEnum.key(i)));
|
||||
*this << metaEnum.value(i);
|
||||
}
|
||||
} else {
|
||||
*this << streamer->getBits();
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
for (int i = 0; i < metaEnum.keyCount(); i++) {
|
||||
hash.addData(metaEnum.key(i), strlen(metaEnum.key(i)) + 1);
|
||||
qint32 value = metaEnum.value(i);
|
||||
hash.addData((const char*)&value, sizeof(qint32));
|
||||
}
|
||||
QByteArray hashResult = hash.result();
|
||||
write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
case TypeStreamer::LIST_CATEGORY:
|
||||
case TypeStreamer::SET_CATEGORY:
|
||||
return *this << streamer->getValueStreamer();
|
||||
|
||||
case TypeStreamer::MAP_CATEGORY:
|
||||
return *this << streamer->getKeyStreamer() << streamer->getValueStreamer();
|
||||
|
||||
default:
|
||||
break; // fall through
|
||||
}
|
||||
// streamable type
|
||||
const QVector<MetaField>& metaFields = streamer->getMetaFields();
|
||||
*this << metaFields.size();
|
||||
if (metaFields.isEmpty()) {
|
||||
return *this;
|
||||
}
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
foreach (const MetaField& metaField, metaFields) {
|
||||
_typeStreamerStreamer << metaField.getStreamer();
|
||||
if (_metadataType == FULL_METADATA) {
|
||||
*this << metaField.getName();
|
||||
} else {
|
||||
hash.addData(metaField.getName().constData(), metaField.getName().size() + 1);
|
||||
}
|
||||
}
|
||||
if (_metadataType == HASH_METADATA) {
|
||||
QByteArray hashResult = hash.result();
|
||||
write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE);
|
||||
}
|
||||
if (_metadataType != NO_METADATA) {
|
||||
*this << (int)streamer->getCategory();
|
||||
streamer->writeMetadata(*this, _metadataType == FULL_METADATA);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1703,6 +1650,31 @@ const TypeStreamer* TypeStreamer::getStreamerToWrite(const QVariant& value) cons
|
|||
return this;
|
||||
}
|
||||
|
||||
void TypeStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||
if (getCategory() != STREAMABLE_CATEGORY) {
|
||||
return;
|
||||
}
|
||||
// streamable type
|
||||
const QVector<MetaField>& metaFields = getMetaFields();
|
||||
out << metaFields.size();
|
||||
if (metaFields.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
foreach (const MetaField& metaField, metaFields) {
|
||||
out << metaField.getStreamer();
|
||||
if (full) {
|
||||
out << metaField.getName();
|
||||
} else {
|
||||
hash.addData(metaField.getName().constData(), metaField.getName().size() + 1);
|
||||
}
|
||||
}
|
||||
if (!full) {
|
||||
QByteArray hashResult = hash.result();
|
||||
out.write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
bool TypeStreamer::equal(const QVariant& first, const QVariant& second) const {
|
||||
return first == second;
|
||||
}
|
||||
|
@ -1842,6 +1814,27 @@ const char* EnumTypeStreamer::getName() const {
|
|||
return _name.constData();
|
||||
}
|
||||
|
||||
void EnumTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||
QMetaEnum metaEnum = getMetaEnum();
|
||||
if (full) {
|
||||
out << metaEnum.keyCount();
|
||||
for (int i = 0; i < metaEnum.keyCount(); i++) {
|
||||
out << QByteArray::fromRawData(metaEnum.key(i), strlen(metaEnum.key(i)));
|
||||
out << metaEnum.value(i);
|
||||
}
|
||||
} else {
|
||||
out << getBits();
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
for (int i = 0; i < metaEnum.keyCount(); i++) {
|
||||
hash.addData(metaEnum.key(i), strlen(metaEnum.key(i)) + 1);
|
||||
qint32 value = metaEnum.value(i);
|
||||
hash.addData((const char*)&value, sizeof(qint32));
|
||||
}
|
||||
QByteArray hashResult = hash.result();
|
||||
out.write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
TypeStreamer::Category EnumTypeStreamer::getCategory() const {
|
||||
return ENUM_CATEGORY;
|
||||
}
|
||||
|
@ -1948,6 +1941,54 @@ void MappedEnumTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const
|
|||
_baseStreamer->setEnumValue(object, value, _mappings);
|
||||
}
|
||||
|
||||
GenericTypeStreamer::GenericTypeStreamer(const QByteArray& name) :
|
||||
_name(name) {
|
||||
}
|
||||
|
||||
const char* GenericTypeStreamer::getName() const {
|
||||
return _name.constData();
|
||||
}
|
||||
|
||||
GenericEnumTypeStreamer::GenericEnumTypeStreamer(const QByteArray& name, const QVector<NameIntPair>& values,
|
||||
int bits, const QByteArray& hash) :
|
||||
GenericTypeStreamer(name),
|
||||
_values(values),
|
||||
_bits(bits),
|
||||
_hash(hash) {
|
||||
|
||||
_type = qMetaTypeId<int>();
|
||||
}
|
||||
|
||||
void GenericEnumTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||
if (full) {
|
||||
out << _values.size();
|
||||
foreach (const NameIntPair& value, _values) {
|
||||
out << value.first << value.second;
|
||||
}
|
||||
} else {
|
||||
out << _bits;
|
||||
if (_hash.isEmpty()) {
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
foreach (const NameIntPair& value, _values) {
|
||||
hash.addData(value.first.constData(), value.first.size() + 1);
|
||||
qint32 intValue = value.second;
|
||||
hash.addData((const char*)&intValue, sizeof(qint32));
|
||||
}
|
||||
const_cast<GenericEnumTypeStreamer*>(this)->_hash = hash.result();
|
||||
}
|
||||
out.write(_hash.constData(), _hash.size() * BITS_IN_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericEnumTypeStreamer::write(Bitstream& out, const QVariant& value) const {
|
||||
int intValue = value.toInt();
|
||||
out.write(&intValue, _bits);
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericEnumTypeStreamer::getCategory() const {
|
||||
return ENUM_CATEGORY;
|
||||
}
|
||||
|
||||
GenericValue::GenericValue(const TypeStreamerPointer& streamer, const QVariant& value) :
|
||||
_streamer(streamer),
|
||||
_value(value) {
|
||||
|
@ -1957,7 +1998,7 @@ bool GenericValue::operator==(const GenericValue& other) const {
|
|||
return _streamer == other._streamer && _value == other._value;
|
||||
}
|
||||
|
||||
const TypeStreamer* GenericTypeStreamer::getStreamerToWrite(const QVariant& value) const {
|
||||
const TypeStreamer* GenericValueStreamer::getStreamerToWrite(const QVariant& value) const {
|
||||
return value.value<GenericValue>().getStreamer().data();
|
||||
}
|
||||
|
||||
|
@ -1990,6 +2031,46 @@ void MappedStreamableTypeStreamer::readRawDelta(Bitstream& in, QVariant& object,
|
|||
}
|
||||
}
|
||||
|
||||
GenericStreamableTypeStreamer::GenericStreamableTypeStreamer(const QByteArray& name,
|
||||
const QVector<StreamerNamePair>& fields, const QByteArray& hash) :
|
||||
GenericTypeStreamer(name),
|
||||
_fields(fields),
|
||||
_hash(hash) {
|
||||
|
||||
_type = qMetaTypeId<QVariantList>();
|
||||
}
|
||||
|
||||
void GenericStreamableTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||
out << _fields.size();
|
||||
foreach (const StreamerNamePair& field, _fields) {
|
||||
out << field.first.data();
|
||||
if (full) {
|
||||
out << field.second;
|
||||
}
|
||||
}
|
||||
if (!full) {
|
||||
if (_hash.isEmpty()) {
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
foreach (const StreamerNamePair& field, _fields) {
|
||||
hash.addData(field.second.constData(), field.second.size() + 1);
|
||||
}
|
||||
const_cast<GenericStreamableTypeStreamer*>(this)->_hash = hash.result();
|
||||
}
|
||||
out.write(_hash.constData(), _hash.size() * BITS_IN_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericStreamableTypeStreamer::write(Bitstream& out, const QVariant& value) const {
|
||||
QVariantList values = value.toList();
|
||||
for (int i = 0; i < _fields.size(); i++) {
|
||||
_fields.at(i).first->write(out, values.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericStreamableTypeStreamer::getCategory() const {
|
||||
return STREAMABLE_CATEGORY;
|
||||
}
|
||||
|
||||
MappedListTypeStreamer::MappedListTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer) :
|
||||
_baseStreamer(baseStreamer),
|
||||
_valueStreamer(valueStreamer) {
|
||||
|
@ -2024,6 +2105,29 @@ void MappedListTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const
|
|||
}
|
||||
}
|
||||
|
||||
GenericListTypeStreamer::GenericListTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer) :
|
||||
GenericTypeStreamer(name),
|
||||
_valueStreamer(valueStreamer) {
|
||||
|
||||
_type = qMetaTypeId<QVariantList>();
|
||||
}
|
||||
|
||||
void GenericListTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||
out << _valueStreamer.data();
|
||||
}
|
||||
|
||||
void GenericListTypeStreamer::write(Bitstream& out, const QVariant& value) const {
|
||||
QVariantList values = value.toList();
|
||||
out << values.size();
|
||||
foreach (const QVariant& element, values) {
|
||||
_valueStreamer->write(out, element);
|
||||
}
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericListTypeStreamer::getCategory() const {
|
||||
return LIST_CATEGORY;
|
||||
}
|
||||
|
||||
MappedSetTypeStreamer::MappedSetTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer) :
|
||||
MappedListTypeStreamer(baseStreamer, valueStreamer) {
|
||||
}
|
||||
|
@ -2040,6 +2144,14 @@ void MappedSetTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const
|
|||
}
|
||||
}
|
||||
|
||||
GenericSetTypeStreamer::GenericSetTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer) :
|
||||
GenericListTypeStreamer(name, valueStreamer) {
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericSetTypeStreamer::getCategory() const {
|
||||
return SET_CATEGORY;
|
||||
}
|
||||
|
||||
MappedMapTypeStreamer::MappedMapTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& keyStreamer,
|
||||
const TypeStreamerPointer& valueStreamer) :
|
||||
_baseStreamer(baseStreamer),
|
||||
|
@ -2084,3 +2196,28 @@ void MappedMapTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const
|
|||
}
|
||||
}
|
||||
|
||||
GenericMapTypeStreamer::GenericMapTypeStreamer(const QByteArray& name, const TypeStreamerPointer& keyStreamer,
|
||||
const TypeStreamerPointer& valueStreamer) :
|
||||
GenericTypeStreamer(name),
|
||||
_keyStreamer(keyStreamer),
|
||||
_valueStreamer(valueStreamer) {
|
||||
|
||||
_type = qMetaTypeId<QVariantPairList>();
|
||||
}
|
||||
|
||||
void GenericMapTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||
out << _keyStreamer.data() << _valueStreamer.data();
|
||||
}
|
||||
|
||||
void GenericMapTypeStreamer::write(Bitstream& out, const QVariant& value) const {
|
||||
QVariantPairList values = value.value<QVariantPairList>();
|
||||
out << values.size();
|
||||
foreach (const QVariantPair& pair, values) {
|
||||
_keyStreamer->write(out, pair.first);
|
||||
_valueStreamer->write(out, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericMapTypeStreamer::getCategory() const {
|
||||
return MAP_CATEGORY;
|
||||
}
|
||||
|
|
|
@ -45,10 +45,16 @@ class TypeStreamer;
|
|||
typedef SharedObjectPointerTemplate<Attribute> AttributePointer;
|
||||
|
||||
typedef QPair<QByteArray, QByteArray> ScopeNamePair;
|
||||
typedef QPair<QByteArray, int> NameIntPair;
|
||||
typedef QSharedPointer<TypeStreamer> TypeStreamerPointer;
|
||||
typedef QVector<PropertyReader> PropertyReaderVector;
|
||||
typedef QVector<PropertyWriter> PropertyWriterVector;
|
||||
|
||||
typedef QPair<QVariant, QVariant> QVariantPair;
|
||||
typedef QList<QVariantPair> QVariantPairList;
|
||||
|
||||
Q_DECLARE_METATYPE(QVariantPairList)
|
||||
|
||||
/// Streams integer identifiers that conform to the following pattern: each ID encountered in the stream is either one that
|
||||
/// has been sent (received) before, or is one more than the highest previously encountered ID (starting at zero). This allows
|
||||
/// us to use the minimum number of bits to encode the IDs.
|
||||
|
@ -856,6 +862,8 @@ public:
|
|||
|
||||
virtual const TypeStreamer* getStreamerToWrite(const QVariant& value) const;
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
|
||||
virtual bool equal(const QVariant& first, const QVariant& second) const;
|
||||
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
|
@ -929,6 +937,7 @@ public:
|
|||
EnumTypeStreamer(const QMetaEnum& metaEnum);
|
||||
|
||||
virtual const char* getName() const;
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual Category getCategory() const;
|
||||
virtual int getBits() const;
|
||||
virtual QMetaEnum getMetaEnum() const;
|
||||
|
@ -966,6 +975,36 @@ private:
|
|||
QHash<int, int> _mappings;
|
||||
};
|
||||
|
||||
/// Base class for generic type streamers, which contain all the metadata required to write out a type.
|
||||
class GenericTypeStreamer : public TypeStreamer {
|
||||
public:
|
||||
|
||||
GenericTypeStreamer(const QByteArray& name);
|
||||
|
||||
virtual const char* getName() const;
|
||||
|
||||
private:
|
||||
|
||||
QByteArray _name;
|
||||
};
|
||||
|
||||
/// A streamer for generic enums.
|
||||
class GenericEnumTypeStreamer : public GenericTypeStreamer {
|
||||
public:
|
||||
|
||||
GenericEnumTypeStreamer(const QByteArray& name, const QVector<NameIntPair>& values, int bits, const QByteArray& hash);
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
QVector<NameIntPair> _values;
|
||||
int _bits;
|
||||
QByteArray _hash;
|
||||
};
|
||||
|
||||
/// Contains a value along with a pointer to its streamer.
|
||||
class GenericValue {
|
||||
public:
|
||||
|
@ -986,7 +1025,7 @@ private:
|
|||
Q_DECLARE_METATYPE(GenericValue)
|
||||
|
||||
/// A streamer class for generic values.
|
||||
class GenericTypeStreamer : public SimpleTypeStreamer<GenericValue> {
|
||||
class GenericValueStreamer : public SimpleTypeStreamer<GenericValue> {
|
||||
public:
|
||||
|
||||
virtual const TypeStreamer* getStreamerToWrite(const QVariant& value) const;
|
||||
|
@ -1022,6 +1061,24 @@ private:
|
|||
QVector<StreamerIndexPair> _fields;
|
||||
};
|
||||
|
||||
typedef QPair<TypeStreamerPointer, QByteArray> StreamerNamePair;
|
||||
|
||||
/// A streamer for generic enums.
|
||||
class GenericStreamableTypeStreamer : public GenericTypeStreamer {
|
||||
public:
|
||||
|
||||
GenericStreamableTypeStreamer(const QByteArray& name, const QVector<StreamerNamePair>& fields, const QByteArray& hash);
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
QVector<StreamerNamePair> _fields;
|
||||
QByteArray _hash;
|
||||
};
|
||||
|
||||
/// Base template for collection streamers.
|
||||
template<class T> class CollectionTypeStreamer : public SimpleTypeStreamer<T> {
|
||||
};
|
||||
|
@ -1030,6 +1087,7 @@ template<class T> class CollectionTypeStreamer : public SimpleTypeStreamer<T> {
|
|||
template<class T> class CollectionTypeStreamer<QList<T> > : public SimpleTypeStreamer<QList<T> > {
|
||||
public:
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const { out << getValueStreamer(); }
|
||||
virtual TypeStreamer::Category getCategory() const { return TypeStreamer::LIST_CATEGORY; }
|
||||
virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId<T>()); }
|
||||
virtual void insert(QVariant& object, const QVariant& value) const {
|
||||
|
@ -1046,6 +1104,7 @@ public:
|
|||
template<class T> class CollectionTypeStreamer<QVector<T> > : public SimpleTypeStreamer<QVector<T> > {
|
||||
public:
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const { out << getValueStreamer(); }
|
||||
virtual TypeStreamer::Category getCategory() const { return TypeStreamer::LIST_CATEGORY; }
|
||||
virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId<T>()); }
|
||||
virtual void insert(QVariant& object, const QVariant& value) const {
|
||||
|
@ -1073,10 +1132,26 @@ protected:
|
|||
TypeStreamerPointer _valueStreamer;
|
||||
};
|
||||
|
||||
/// A streamer for generic lists.
|
||||
class GenericListTypeStreamer : public GenericTypeStreamer {
|
||||
public:
|
||||
|
||||
GenericListTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer);
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
TypeStreamerPointer _valueStreamer;
|
||||
};
|
||||
|
||||
/// A streamer for set types.
|
||||
template<class T> class CollectionTypeStreamer<QSet<T> > : public SimpleTypeStreamer<QSet<T> > {
|
||||
public:
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const { out << getValueStreamer(); }
|
||||
virtual TypeStreamer::Category getCategory() const { return TypeStreamer::SET_CATEGORY; }
|
||||
virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId<T>()); }
|
||||
virtual void insert(QVariant& object, const QVariant& value) const {
|
||||
|
@ -1094,10 +1169,20 @@ public:
|
|||
virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
|
||||
};
|
||||
|
||||
/// A streamer for generic sets.
|
||||
class GenericSetTypeStreamer : public GenericListTypeStreamer {
|
||||
public:
|
||||
|
||||
GenericSetTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer);
|
||||
|
||||
virtual Category getCategory() const;
|
||||
};
|
||||
|
||||
/// A streamer for hash types.
|
||||
template<class K, class V> class CollectionTypeStreamer<QHash<K, V> > : public SimpleTypeStreamer<QHash<K, V> > {
|
||||
public:
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const { out << getKeyStreamer() << getValueStreamer(); }
|
||||
virtual TypeStreamer::Category getCategory() const { return TypeStreamer::MAP_CATEGORY; }
|
||||
virtual const TypeStreamer* getKeyStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId<K>()); }
|
||||
virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId<V>()); }
|
||||
|
@ -1126,6 +1211,23 @@ private:
|
|||
TypeStreamerPointer _valueStreamer;
|
||||
};
|
||||
|
||||
/// A streamer for generic maps.
|
||||
class GenericMapTypeStreamer : public GenericTypeStreamer {
|
||||
public:
|
||||
|
||||
GenericMapTypeStreamer(const QByteArray& name, const TypeStreamerPointer& keyStreamer,
|
||||
const TypeStreamerPointer& valueStreamer);
|
||||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
TypeStreamerPointer _keyStreamer;
|
||||
TypeStreamerPointer _valueStreamer;
|
||||
};
|
||||
|
||||
/// Macro for registering simple type streamers.
|
||||
#define REGISTER_SIMPLE_TYPE_STREAMER(X) static int X##Streamer = \
|
||||
Bitstream::registerTypeStreamer(qMetaTypeId<X>(), new SimpleTypeStreamer<X>());
|
||||
|
|
Loading…
Reference in a new issue