mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-11 17:15:20 +02:00
Collection streaming (untested).
This commit is contained in:
parent
b84499c83b
commit
a4cc15a2cd
2 changed files with 109 additions and 17 deletions
|
@ -577,6 +577,22 @@ Bitstream& Bitstream::operator<(const TypeStreamer* streamer) {
|
|||
if (_metadataType == NO_METADATA) {
|
||||
return *this;
|
||||
}
|
||||
TypeStreamer::Category category = streamer->getCategory();
|
||||
*this << (int)category;
|
||||
switch (category) {
|
||||
case TypeStreamer::SIMPLE_CATEGORY:
|
||||
return *this;
|
||||
|
||||
case TypeStreamer::LIST_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()) {
|
||||
|
@ -612,6 +628,40 @@ Bitstream& Bitstream::operator>(TypeReader& reader) {
|
|||
reader = TypeReader(typeName, streamer);
|
||||
return *this;
|
||||
}
|
||||
int category;
|
||||
*this >> category;
|
||||
switch (category) {
|
||||
case TypeStreamer::SIMPLE_CATEGORY:
|
||||
reader = TypeReader(typeName, streamer);
|
||||
return *this;
|
||||
|
||||
case TypeStreamer::LIST_CATEGORY: {
|
||||
TypeReader valueReader;
|
||||
*this >> valueReader;
|
||||
if (streamer && streamer->getCategory() == TypeStreamer::LIST_CATEGORY &&
|
||||
valueReader.matchesExactly(streamer->getValueStreamer())) {
|
||||
reader = TypeReader(typeName, streamer);
|
||||
} else {
|
||||
reader = TypeReader(typeName, streamer, false, TypeReaderPointer(),
|
||||
TypeReaderPointer(new TypeReader(valueReader)));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
case TypeStreamer::MAP_CATEGORY: {
|
||||
TypeReader keyReader, valueReader;
|
||||
*this >> keyReader >> valueReader;
|
||||
if (streamer && streamer->getCategory() == TypeStreamer::MAP_CATEGORY &&
|
||||
keyReader.matchesExactly(streamer->getKeyStreamer()) &&
|
||||
valueReader.matchesExactly(streamer->getValueStreamer())) {
|
||||
reader = TypeReader(typeName, streamer);
|
||||
} else {
|
||||
reader = TypeReader(typeName, streamer, false, TypeReaderPointer(new TypeReader(keyReader)),
|
||||
TypeReaderPointer(new TypeReader(valueReader)));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
// streamable type
|
||||
int fieldCount;
|
||||
*this >> fieldCount;
|
||||
QVector<FieldReader> fields(fieldCount);
|
||||
|
@ -664,20 +714,20 @@ Bitstream& Bitstream::operator>(TypeReader& reader) {
|
|||
// if all fields are the same type and in the right order, we can use the (more efficient) default streamer
|
||||
const QVector<MetaField>& localFields = streamer->getMetaFields();
|
||||
if (fieldCount != localFields.size()) {
|
||||
reader = TypeReader(typeName, streamer, false, fields);
|
||||
reader = TypeReader(typeName, streamer, false, TypeReaderPointer(), TypeReaderPointer(), fields);
|
||||
return *this;
|
||||
}
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
const FieldReader& fieldReader = fields.at(i);
|
||||
if (!fieldReader.getReader().matchesExactly(localFields.at(i).getStreamer()) || fieldReader.getIndex() != i) {
|
||||
reader = TypeReader(typeName, streamer, false, fields);
|
||||
reader = TypeReader(typeName, streamer, false, TypeReaderPointer(), TypeReaderPointer(), fields);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
reader = TypeReader(typeName, streamer);
|
||||
return *this;
|
||||
}
|
||||
reader = TypeReader(typeName, streamer, false, fields);
|
||||
reader = TypeReader(typeName, streamer, false, TypeReaderPointer(), TypeReaderPointer(), fields);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -773,11 +823,13 @@ QVector<PropertyReader> Bitstream::getPropertyReaders(const QMetaObject* metaObj
|
|||
return propertyReaders;
|
||||
}
|
||||
|
||||
TypeReader::TypeReader(const QByteArray& typeName, const TypeStreamer* streamer,
|
||||
bool exactMatch, const QVector<FieldReader>& fields) :
|
||||
TypeReader::TypeReader(const QByteArray& typeName, const TypeStreamer* streamer, bool exactMatch,
|
||||
const TypeReaderPointer& keyReader, const TypeReaderPointer& valueReader, const QVector<FieldReader>& fields) :
|
||||
_typeName(typeName),
|
||||
_streamer(streamer),
|
||||
_exactMatch(exactMatch),
|
||||
_keyReader(keyReader),
|
||||
_valueReader(valueReader),
|
||||
_fields(fields) {
|
||||
}
|
||||
|
||||
|
@ -786,8 +838,29 @@ QVariant TypeReader::read(Bitstream& in) const {
|
|||
return _streamer->read(in);
|
||||
}
|
||||
QVariant object = _streamer ? QVariant(_streamer->getType(), 0) : QVariant();
|
||||
foreach (const FieldReader& field, _fields) {
|
||||
field.read(in, _streamer, object);
|
||||
if (_valueReader) {
|
||||
int size;
|
||||
in >> size;
|
||||
if (_keyReader) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
QVariant key = _keyReader->read(in);
|
||||
QVariant value = _valueReader->read(in);
|
||||
if (_streamer) {
|
||||
_streamer->insert(object, key, value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < size; i++) {
|
||||
QVariant value = _valueReader->read(in);
|
||||
if (_streamer) {
|
||||
_streamer->insert(object, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (const FieldReader& field, _fields) {
|
||||
field.read(in, _streamer, object);
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
@ -866,6 +939,10 @@ void TypeStreamer::setField(int index, QVariant& object, const QVariant& value)
|
|||
// nothing by default
|
||||
}
|
||||
|
||||
TypeStreamer::Category TypeStreamer::getCategory() const {
|
||||
return SIMPLE_CATEGORY;
|
||||
}
|
||||
|
||||
const TypeStreamer* TypeStreamer::getKeyStreamer() const {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -874,7 +951,7 @@ const TypeStreamer* TypeStreamer::getValueStreamer() const {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void TypeStreamer::append(QVariant& object, const QVariant& element) const {
|
||||
void TypeStreamer::insert(QVariant& object, const QVariant& element) const {
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
|
|
|
@ -444,12 +444,15 @@ template<class K, class V> inline Bitstream& Bitstream::operator>>(QHash<K, V>&
|
|||
return *this;
|
||||
}
|
||||
|
||||
typedef QSharedPointer<TypeReader> TypeReaderPointer;
|
||||
|
||||
/// Contains the information required to read a type from the stream.
|
||||
class TypeReader {
|
||||
public:
|
||||
|
||||
TypeReader(const QByteArray& typeName = QByteArray(), const TypeStreamer* streamer = NULL,
|
||||
bool exactMatch = true, const QVector<FieldReader>& fields = QVector<FieldReader>());
|
||||
TypeReader(const QByteArray& typeName = QByteArray(), const TypeStreamer* streamer = NULL, bool exactMatch = true,
|
||||
const TypeReaderPointer& keyReader = TypeReaderPointer(), const TypeReaderPointer& valueReader = TypeReaderPointer(),
|
||||
const QVector<FieldReader>& fields = QVector<FieldReader>());
|
||||
|
||||
const QByteArray& getTypeName() const { return _typeName; }
|
||||
const TypeStreamer* getStreamer() const { return _streamer; }
|
||||
|
@ -466,6 +469,8 @@ private:
|
|||
QByteArray _typeName;
|
||||
const TypeStreamer* _streamer;
|
||||
bool _exactMatch;
|
||||
TypeReaderPointer _keyReader;
|
||||
TypeReaderPointer _valueReader;
|
||||
QVector<FieldReader> _fields;
|
||||
};
|
||||
|
||||
|
@ -552,8 +557,6 @@ Q_DECLARE_METATYPE(const QMetaObject*)
|
|||
class TypeStreamer {
|
||||
public:
|
||||
|
||||
enum Category { SIMPLE_CATEGORY, STREAMABLE_CATEGORY };
|
||||
|
||||
virtual ~TypeStreamer();
|
||||
|
||||
void setType(int type) { _type = type; }
|
||||
|
@ -565,11 +568,15 @@ public:
|
|||
virtual const QVector<MetaField>& getMetaFields() const;
|
||||
virtual int getFieldIndex(const QByteArray& name) const;
|
||||
virtual void setField(int index, QVariant& object, const QVariant& value) const;
|
||||
|
||||
enum Category { SIMPLE_CATEGORY, STREAMABLE_CATEGORY, LIST_CATEGORY, MAP_CATEGORY };
|
||||
|
||||
virtual Category getCategory() const;
|
||||
|
||||
virtual const TypeStreamer* getKeyStreamer() const;
|
||||
virtual const TypeStreamer* getValueStreamer() const;
|
||||
|
||||
virtual void append(QVariant& object, const QVariant& element) const;
|
||||
virtual void insert(QVariant& object, const QVariant& value) const;
|
||||
virtual void insert(QVariant& object, const QVariant& key, const QVariant& value) const;
|
||||
|
||||
private:
|
||||
|
@ -589,6 +596,7 @@ public:
|
|||
template<class T> class StreamableTypeStreamer : public SimpleTypeStreamer<T> {
|
||||
public:
|
||||
|
||||
virtual TypeStreamer::Category getCategory() const { return TypeStreamer::STREAMABLE_CATEGORY; }
|
||||
virtual const QVector<MetaField>& getMetaFields() const { return T::getMetaFields(); }
|
||||
virtual int getFieldIndex(const QByteArray& name) const { return T::getFieldIndex(name); }
|
||||
virtual void setField(int index, QVariant& object, const QVariant& value) const {
|
||||
|
@ -603,22 +611,29 @@ template<class T> class CollectionTypeStreamer : public SimpleTypeStreamer<T> {
|
|||
template<class T> class CollectionTypeStreamer<QList<T> > : public SimpleTypeStreamer<QList<T> > {
|
||||
public:
|
||||
|
||||
virtual void append(QVariant& object, const QVariant& element) const {
|
||||
static_cast<QList<T>*>(object.data())->append(element.value<T>()); }
|
||||
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 {
|
||||
static_cast<QList<T>*>(object.data())->append(value.value<T>()); }
|
||||
};
|
||||
|
||||
/// A streamer for set types.
|
||||
template<class T> class CollectionTypeStreamer<QSet<T> > : public SimpleTypeStreamer<QSet<T> > {
|
||||
public:
|
||||
|
||||
virtual void append(QVariant& object, const QVariant& element) const {
|
||||
static_cast<QSet<T>*>(object.data())->insert(element.value<T>()); }
|
||||
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 {
|
||||
static_cast<QSet<T>*>(object.data())->insert(value.value<T>()); }
|
||||
};
|
||||
|
||||
/// A streamer for hash types.
|
||||
template<class K, class V> class CollectionTypeStreamer<QHash<K, V> > : public SimpleTypeStreamer<QHash<K, V> > {
|
||||
public:
|
||||
|
||||
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>()); }
|
||||
virtual void insert(QVariant& object, const QVariant& key, const QVariant& value) const {
|
||||
static_cast<QHash<K, V>*>(object.data())->insert(key.value<K>(), value.value<V>()); }
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue