mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 06:16:18 +02:00
Merge pull request #3023 from ey6es/metavoxels
Refactored type/object streaming, added support for reading into/writing from "generic" containers that don't require the original classes/types.
This commit is contained in:
commit
41b3e3e4ea
6 changed files with 1337 additions and 727 deletions
File diff suppressed because it is too large
Load diff
|
@ -35,19 +35,25 @@ class QUrl;
|
|||
class Attribute;
|
||||
class AttributeValue;
|
||||
class Bitstream;
|
||||
class FieldReader;
|
||||
class GenericValue;
|
||||
class ObjectReader;
|
||||
class ObjectStreamer;
|
||||
class OwnedAttributeValue;
|
||||
class PropertyReader;
|
||||
class PropertyWriter;
|
||||
class TypeReader;
|
||||
class TypeStreamer;
|
||||
|
||||
typedef SharedObjectPointerTemplate<Attribute> AttributePointer;
|
||||
|
||||
typedef QPair<QByteArray, QByteArray> ScopeNamePair;
|
||||
typedef QVector<PropertyReader> PropertyReaderVector;
|
||||
typedef QVector<PropertyWriter> PropertyWriterVector;
|
||||
typedef QPair<QByteArray, int> NameIntPair;
|
||||
typedef QSharedPointer<ObjectStreamer> ObjectStreamerPointer;
|
||||
typedef QWeakPointer<ObjectStreamer> WeakObjectStreamerPointer;
|
||||
typedef QSharedPointer<TypeStreamer> TypeStreamerPointer;
|
||||
typedef QWeakPointer<TypeStreamer> WeakTypeStreamerPointer;
|
||||
|
||||
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
|
||||
|
@ -197,7 +203,7 @@ public:
|
|||
|
||||
class WriteMappings {
|
||||
public:
|
||||
QHash<const QMetaObject*, int> metaObjectOffsets;
|
||||
QHash<const ObjectStreamer*, int> objectStreamerOffsets;
|
||||
QHash<const TypeStreamer*, int> typeStreamerOffsets;
|
||||
QHash<AttributePointer, int> attributeOffsets;
|
||||
QHash<QScriptString, int> scriptStringOffsets;
|
||||
|
@ -206,8 +212,8 @@ public:
|
|||
|
||||
class ReadMappings {
|
||||
public:
|
||||
QHash<int, ObjectReader> metaObjectValues;
|
||||
QHash<int, TypeReader> typeStreamerValues;
|
||||
QHash<int, ObjectStreamerPointer> objectStreamerValues;
|
||||
QHash<int, TypeStreamerPointer> typeStreamerValues;
|
||||
QHash<int, AttributePointer> attributeValues;
|
||||
QHash<int, QScriptString> scriptStringValues;
|
||||
QHash<int, SharedObjectPointer> sharedObjectValues;
|
||||
|
@ -232,8 +238,17 @@ public:
|
|||
|
||||
enum MetadataType { NO_METADATA, HASH_METADATA, FULL_METADATA };
|
||||
|
||||
enum GenericsMode { NO_GENERICS, FALLBACK_GENERICS, ALL_GENERICS };
|
||||
|
||||
/// Creates a new bitstream. Note: the stream may be used for reading or writing, but not both.
|
||||
Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA, QObject* parent = NULL);
|
||||
/// \param metadataType the metadata type, which determines the amount of version-resiliency: with no metadata, all types
|
||||
/// must match exactly; with hash metadata, any types which do not match exactly will be ignored; with full metadata,
|
||||
/// fields (and enum values, etc.) will be remapped by name
|
||||
/// \param genericsMode the generics mode, which determines which types will be replaced by generic equivalents: with
|
||||
/// no generics, no generics will be created; with fallback generics, generics will be created for any unknown types; with
|
||||
/// all generics, generics will be created for all non-simple types
|
||||
Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA,
|
||||
GenericsMode = NO_GENERICS, QObject* parent = NULL);
|
||||
|
||||
/// Substitutes the supplied metaobject for the given class name's default mapping.
|
||||
void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject);
|
||||
|
@ -364,6 +379,9 @@ public:
|
|||
Bitstream& operator<<(const AttributeValue& attributeValue);
|
||||
Bitstream& operator>>(OwnedAttributeValue& attributeValue);
|
||||
|
||||
Bitstream& operator<<(const GenericValue& value);
|
||||
Bitstream& operator>>(GenericValue& value);
|
||||
|
||||
template<class T> Bitstream& operator<<(const QList<T>& list);
|
||||
template<class T> Bitstream& operator>>(QList<T>& list);
|
||||
|
||||
|
@ -381,11 +399,14 @@ public:
|
|||
|
||||
Bitstream& operator<<(const QMetaObject* metaObject);
|
||||
Bitstream& operator>>(const QMetaObject*& metaObject);
|
||||
Bitstream& operator>>(ObjectReader& objectReader);
|
||||
|
||||
Bitstream& operator<<(const ObjectStreamer* streamer);
|
||||
Bitstream& operator>>(const ObjectStreamer*& streamer);
|
||||
Bitstream& operator>>(ObjectStreamerPointer& streamer);
|
||||
|
||||
Bitstream& operator<<(const TypeStreamer* streamer);
|
||||
Bitstream& operator>>(const TypeStreamer*& streamer);
|
||||
Bitstream& operator>>(TypeReader& reader);
|
||||
Bitstream& operator>>(TypeStreamerPointer& streamer);
|
||||
|
||||
Bitstream& operator<<(const AttributePointer& attribute);
|
||||
Bitstream& operator>>(AttributePointer& attribute);
|
||||
|
@ -399,11 +420,11 @@ public:
|
|||
Bitstream& operator<<(const SharedObjectPointer& object);
|
||||
Bitstream& operator>>(SharedObjectPointer& object);
|
||||
|
||||
Bitstream& operator<(const QMetaObject* metaObject);
|
||||
Bitstream& operator>(ObjectReader& objectReader);
|
||||
Bitstream& operator<(const ObjectStreamer* streamer);
|
||||
Bitstream& operator>(ObjectStreamerPointer& streamer);
|
||||
|
||||
Bitstream& operator<(const TypeStreamer* streamer);
|
||||
Bitstream& operator>(TypeReader& reader);
|
||||
Bitstream& operator>(TypeStreamerPointer& streamer);
|
||||
|
||||
Bitstream& operator<(const AttributePointer& attribute);
|
||||
Bitstream& operator>(AttributePointer& attribute);
|
||||
|
@ -424,14 +445,18 @@ private slots:
|
|||
|
||||
private:
|
||||
|
||||
ObjectStreamerPointer readGenericObjectStreamer(const QByteArray& name);
|
||||
TypeStreamerPointer readGenericTypeStreamer(const QByteArray& name, int category);
|
||||
|
||||
QDataStream& _underlying;
|
||||
quint8 _byte;
|
||||
int _position;
|
||||
|
||||
MetadataType _metadataType;
|
||||
GenericsMode _genericsMode;
|
||||
|
||||
RepeatedValueStreamer<const QMetaObject*, const QMetaObject*, ObjectReader> _metaObjectStreamer;
|
||||
RepeatedValueStreamer<const TypeStreamer*, const TypeStreamer*, TypeReader> _typeStreamerStreamer;
|
||||
RepeatedValueStreamer<const ObjectStreamer*, const ObjectStreamer*, ObjectStreamerPointer> _objectStreamerStreamer;
|
||||
RepeatedValueStreamer<const TypeStreamer*, const TypeStreamer*, TypeStreamerPointer> _typeStreamerStreamer;
|
||||
RepeatedValueStreamer<AttributePointer> _attributeStreamer;
|
||||
RepeatedValueStreamer<QScriptString> _scriptStringStreamer;
|
||||
RepeatedValueStreamer<SharedObjectPointer, SharedObject*> _sharedObjectStreamer;
|
||||
|
@ -447,17 +472,17 @@ private:
|
|||
static QMultiHash<const QMetaObject*, const QMetaObject*>& getMetaObjectSubClasses();
|
||||
static QHash<int, const TypeStreamer*>& getTypeStreamers();
|
||||
|
||||
static const QHash<const QMetaObject*, const ObjectStreamer*>& getObjectStreamers();
|
||||
static QHash<const QMetaObject*, const ObjectStreamer*> createObjectStreamers();
|
||||
|
||||
static const QHash<ScopeNamePair, const TypeStreamer*>& getEnumStreamers();
|
||||
static QHash<ScopeNamePair, const TypeStreamer*> createEnumStreamers();
|
||||
|
||||
static const QHash<QByteArray, const TypeStreamer*>& getEnumStreamersByName();
|
||||
static QHash<QByteArray, const TypeStreamer*> createEnumStreamersByName();
|
||||
|
||||
static const QHash<const QMetaObject*, PropertyReaderVector>& getPropertyReaders();
|
||||
static QHash<const QMetaObject*, PropertyReaderVector> createPropertyReaders();
|
||||
|
||||
static const QHash<const QMetaObject*, PropertyWriterVector>& getPropertyWriters();
|
||||
static QHash<const QMetaObject*, PropertyWriterVector> createPropertyWriters();
|
||||
static const TypeStreamer* getInvalidTypeStreamer();
|
||||
static const TypeStreamer* createInvalidTypeStreamer();
|
||||
};
|
||||
|
||||
template<class T> inline void Bitstream::writeDelta(const T& value, const T& reference) {
|
||||
|
@ -741,133 +766,75 @@ template<class K, class V> inline Bitstream& Bitstream::operator>>(QHash<K, V>&
|
|||
return *this;
|
||||
}
|
||||
|
||||
typedef QSharedPointer<TypeReader> TypeReaderPointer;
|
||||
typedef QPair<TypeStreamerPointer, QMetaProperty> StreamerPropertyPair;
|
||||
|
||||
/// Contains the information required to read a type from the stream.
|
||||
class TypeReader {
|
||||
/// Contains the information required to stream an object.
|
||||
class ObjectStreamer {
|
||||
public:
|
||||
|
||||
enum Type { SIMPLE_TYPE, ENUM_TYPE, STREAMABLE_TYPE, LIST_TYPE, SET_TYPE, MAP_TYPE };
|
||||
|
||||
TypeReader(const QByteArray& typeName = QByteArray(), const TypeStreamer* streamer = NULL);
|
||||
|
||||
TypeReader(const QByteArray& typeName, const TypeStreamer* streamer, int bits, const QHash<int, int>& mappings);
|
||||
|
||||
TypeReader(const QByteArray& typeName, const TypeStreamer* streamer, const QVector<FieldReader>& fields);
|
||||
ObjectStreamer(const QMetaObject* metaObject);
|
||||
|
||||
TypeReader(const QByteArray& typeName, const TypeStreamer* streamer, Type type,
|
||||
const TypeReaderPointer& valueReader);
|
||||
|
||||
TypeReader(const QByteArray& typeName, const TypeStreamer* streamer,
|
||||
const TypeReaderPointer& keyReader, const TypeReaderPointer& valueReader);
|
||||
|
||||
const QByteArray& getTypeName() const { return _typeName; }
|
||||
const TypeStreamer* getStreamer() const { return _streamer; }
|
||||
|
||||
QVariant read(Bitstream& in) const;
|
||||
void readDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
|
||||
void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
|
||||
|
||||
bool matchesExactly(const TypeStreamer* streamer) const;
|
||||
|
||||
bool operator==(const TypeReader& other) const { return _typeName == other._typeName; }
|
||||
bool operator!=(const TypeReader& other) const { return _typeName != other._typeName; }
|
||||
|
||||
private:
|
||||
|
||||
QByteArray _typeName;
|
||||
const TypeStreamer* _streamer;
|
||||
bool _exactMatch;
|
||||
Type _type;
|
||||
int _bits;
|
||||
QHash<int, int> _mappings;
|
||||
TypeReaderPointer _keyReader;
|
||||
TypeReaderPointer _valueReader;
|
||||
QVector<FieldReader> _fields;
|
||||
};
|
||||
|
||||
uint qHash(const TypeReader& typeReader, uint seed = 0);
|
||||
|
||||
QDebug& operator<<(QDebug& debug, const TypeReader& typeReader);
|
||||
|
||||
/// Contains the information required to read a metatype field from the stream and apply it.
|
||||
class FieldReader {
|
||||
public:
|
||||
|
||||
FieldReader(const TypeReader& reader = TypeReader(), int index = -1);
|
||||
|
||||
const TypeReader& getReader() const { return _reader; }
|
||||
int getIndex() const { return _index; }
|
||||
|
||||
void read(Bitstream& in, const TypeStreamer* streamer, QVariant& object) const;
|
||||
void readDelta(Bitstream& in, const TypeStreamer* streamer, QVariant& object, const QVariant& reference) const;
|
||||
|
||||
private:
|
||||
|
||||
TypeReader _reader;
|
||||
int _index;
|
||||
};
|
||||
|
||||
/// Contains the information required to read an object from the stream.
|
||||
class ObjectReader {
|
||||
public:
|
||||
|
||||
ObjectReader(const QByteArray& className = QByteArray(), const QMetaObject* metaObject = NULL,
|
||||
const QVector<PropertyReader>& properties = QVector<PropertyReader>());
|
||||
|
||||
const QByteArray& getClassName() const { return _className; }
|
||||
const QMetaObject* getMetaObject() const { return _metaObject; }
|
||||
const ObjectStreamerPointer& getSelf() const { return _self; }
|
||||
|
||||
virtual const char* getName() const = 0;
|
||||
virtual const QVector<StreamerPropertyPair>& getProperties() const;
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const = 0;
|
||||
virtual void write(Bitstream& out, const QObject* object) const = 0;
|
||||
virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const = 0;
|
||||
virtual QObject* read(Bitstream& in, QObject* object = NULL) const = 0;
|
||||
virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
friend class Bitstream;
|
||||
|
||||
QObject* read(Bitstream& in, QObject* object = NULL) const;
|
||||
QObject* readDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const;
|
||||
|
||||
bool operator==(const ObjectReader& other) const { return _className == other._className; }
|
||||
bool operator!=(const ObjectReader& other) const { return _className != other._className; }
|
||||
|
||||
private:
|
||||
|
||||
QByteArray _className;
|
||||
const QMetaObject* _metaObject;
|
||||
QVector<PropertyReader> _properties;
|
||||
ObjectStreamerPointer _self;
|
||||
};
|
||||
|
||||
uint qHash(const ObjectReader& objectReader, uint seed = 0);
|
||||
|
||||
QDebug& operator<<(QDebug& debug, const ObjectReader& objectReader);
|
||||
|
||||
/// Contains the information required to read an object property from the stream and apply it.
|
||||
class PropertyReader {
|
||||
/// A streamer that maps to a local class.
|
||||
class MappedObjectStreamer : public ObjectStreamer {
|
||||
public:
|
||||
|
||||
PropertyReader(const TypeReader& reader = TypeReader(), const QMetaProperty& property = QMetaProperty());
|
||||
|
||||
const TypeReader& getReader() const { return _reader; }
|
||||
|
||||
void read(Bitstream& in, QObject* object) const;
|
||||
void readDelta(Bitstream& in, QObject* object, const QObject* reference) const;
|
||||
|
||||
private:
|
||||
|
||||
TypeReader _reader;
|
||||
QMetaProperty _property;
|
||||
};
|
||||
|
||||
/// Contains the information required to obtain an object property and write it to the stream.
|
||||
class PropertyWriter {
|
||||
public:
|
||||
|
||||
PropertyWriter(const QMetaProperty& property = QMetaProperty(), const TypeStreamer* streamer = NULL);
|
||||
|
||||
const QMetaProperty& getProperty() const { return _property; }
|
||||
const TypeStreamer* getStreamer() const { return _streamer; }
|
||||
|
||||
void write(Bitstream& out, const QObject* object) const;
|
||||
void writeDelta(Bitstream& out, const QObject* object, const QObject* reference) const;
|
||||
MappedObjectStreamer(const QMetaObject* metaObject, const QVector<StreamerPropertyPair>& properties);
|
||||
|
||||
virtual const char* getName() const;
|
||||
virtual const QVector<StreamerPropertyPair>& getProperties() const;
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QObject* object) const;
|
||||
virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const;
|
||||
virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
|
||||
virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const;
|
||||
|
||||
private:
|
||||
|
||||
QMetaProperty _property;
|
||||
const TypeStreamer* _streamer;
|
||||
QVector<StreamerPropertyPair> _properties;
|
||||
};
|
||||
|
||||
typedef QPair<TypeStreamerPointer, QByteArray> StreamerNamePair;
|
||||
|
||||
/// A streamer for generic objects.
|
||||
class GenericObjectStreamer : public ObjectStreamer {
|
||||
public:
|
||||
|
||||
GenericObjectStreamer(const QByteArray& name, const QVector<StreamerNamePair>& properties, const QByteArray& hash);
|
||||
|
||||
virtual const char* getName() const;
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QObject* object) const;
|
||||
virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const;
|
||||
virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
|
||||
virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const;
|
||||
|
||||
private:
|
||||
|
||||
friend class Bitstream;
|
||||
|
||||
QByteArray _name;
|
||||
WeakObjectStreamerPointer _weakSelf;
|
||||
QVector<StreamerNamePair> _properties;
|
||||
QByteArray _hash;
|
||||
};
|
||||
|
||||
/// Describes a metatype field.
|
||||
|
@ -890,27 +857,75 @@ Q_DECLARE_METATYPE(const QMetaObject*)
|
|||
/// Macro for registering streamable meta-objects.
|
||||
#define REGISTER_META_OBJECT(x) static int x##Registration = Bitstream::registerMetaObject(#x, &x::staticMetaObject);
|
||||
|
||||
/// Contains a value along with a pointer to its streamer.
|
||||
class GenericValue {
|
||||
public:
|
||||
|
||||
GenericValue(const TypeStreamerPointer& streamer = TypeStreamerPointer(), const QVariant& value = QVariant());
|
||||
|
||||
const TypeStreamerPointer& getStreamer() const { return _streamer; }
|
||||
const QVariant& getValue() const { return _value; }
|
||||
|
||||
bool operator==(const GenericValue& other) const;
|
||||
|
||||
private:
|
||||
|
||||
TypeStreamerPointer _streamer;
|
||||
QVariant _value;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(GenericValue)
|
||||
|
||||
/// Contains a list of property values along with a pointer to their metadata.
|
||||
class GenericSharedObject : public SharedObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
GenericSharedObject(const ObjectStreamerPointer& streamer);
|
||||
|
||||
const ObjectStreamerPointer& getStreamer() const { return _streamer; }
|
||||
|
||||
void setValues(const QVariantList& values) { _values = values; }
|
||||
const QVariantList& getValues() const { return _values; }
|
||||
|
||||
private:
|
||||
|
||||
ObjectStreamerPointer _streamer;
|
||||
QVariantList _values;
|
||||
};
|
||||
|
||||
/// Interface for objects that can write values to and read values from bitstreams.
|
||||
class TypeStreamer {
|
||||
public:
|
||||
|
||||
enum Category { SIMPLE_CATEGORY, ENUM_CATEGORY, STREAMABLE_CATEGORY, LIST_CATEGORY, SET_CATEGORY, MAP_CATEGORY };
|
||||
|
||||
virtual ~TypeStreamer();
|
||||
|
||||
void setType(int type) { _type = type; }
|
||||
int getType() const { return _type; }
|
||||
|
||||
const TypeStreamerPointer& getSelf() const { return _self; }
|
||||
|
||||
virtual const char* getName() const;
|
||||
|
||||
virtual bool equal(const QVariant& first, const QVariant& second) const = 0;
|
||||
virtual const TypeStreamer* getStreamerToWrite(const QVariant& value) const;
|
||||
|
||||
virtual void write(Bitstream& out, const QVariant& value) const = 0;
|
||||
virtual QVariant read(Bitstream& in) const = 0;
|
||||
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;
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
|
||||
virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const = 0;
|
||||
virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const = 0;
|
||||
virtual void writeVariant(Bitstream& out, const QVariant& value) const;
|
||||
virtual QVariant readVariant(Bitstream& in) const;
|
||||
|
||||
virtual void writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const = 0;
|
||||
virtual void readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const = 0;
|
||||
virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const;
|
||||
virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const;
|
||||
|
||||
virtual void writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const;
|
||||
virtual void readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const;
|
||||
|
||||
virtual void setEnumValue(QVariant& object, int value, const QHash<int, int>& mappings) const;
|
||||
|
||||
|
@ -919,7 +934,7 @@ public:
|
|||
virtual void setField(QVariant& object, int index, const QVariant& value) const;
|
||||
virtual QVariant getField(const QVariant& object, int index) const;
|
||||
|
||||
virtual TypeReader::Type getReaderType() const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
virtual int getBits() const;
|
||||
virtual QMetaEnum getMetaEnum() const;
|
||||
|
@ -937,9 +952,12 @@ public:
|
|||
virtual QVariant getValue(const QVariant& object, int index) const;
|
||||
virtual void setValue(QVariant& object, int index, const QVariant& value) const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
friend class Bitstream;
|
||||
|
||||
int _type;
|
||||
TypeStreamerPointer _self;
|
||||
};
|
||||
|
||||
QDebug& operator<<(QDebug& debug, const TypeStreamer* typeStreamer);
|
||||
|
@ -971,7 +989,8 @@ public:
|
|||
EnumTypeStreamer(const QMetaEnum& metaEnum);
|
||||
|
||||
virtual const char* getName() const;
|
||||
virtual TypeReader::Type getReaderType() const;
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual Category getCategory() const;
|
||||
virtual int getBits() const;
|
||||
virtual QMetaEnum getMetaEnum() const;
|
||||
virtual bool equal(const QVariant& first, const QVariant& second) const;
|
||||
|
@ -992,11 +1011,62 @@ private:
|
|||
int _bits;
|
||||
};
|
||||
|
||||
/// A streamer class for enums that maps to a local type.
|
||||
class MappedEnumTypeStreamer : public TypeStreamer {
|
||||
public:
|
||||
|
||||
MappedEnumTypeStreamer(const TypeStreamer* baseStreamer, int bits, const QHash<int, int>& mappings);
|
||||
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
|
||||
|
||||
private:
|
||||
|
||||
const TypeStreamer* _baseStreamer;
|
||||
int _bits;
|
||||
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;
|
||||
virtual QVariant readVariant(Bitstream& in) const;
|
||||
|
||||
protected:
|
||||
|
||||
friend class Bitstream;
|
||||
|
||||
QByteArray _name;
|
||||
WeakTypeStreamerPointer _weakSelf;
|
||||
};
|
||||
|
||||
/// 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 QVariant read(Bitstream& in) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
QVector<NameIntPair> _values;
|
||||
int _bits;
|
||||
QByteArray _hash;
|
||||
};
|
||||
|
||||
/// A streamer for types compiled by mtc.
|
||||
template<class T> class StreamableTypeStreamer : public SimpleTypeStreamer<T> {
|
||||
public:
|
||||
|
||||
virtual TypeReader::Type getReaderType() const { return TypeReader::STREAMABLE_TYPE; }
|
||||
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(QVariant& object, int index, const QVariant& value) const {
|
||||
|
@ -1005,6 +1075,40 @@ public:
|
|||
return static_cast<const T*>(object.constData())->getField(index); }
|
||||
};
|
||||
|
||||
typedef QPair<TypeStreamerPointer, int> StreamerIndexPair;
|
||||
|
||||
/// A streamer class for streamables that maps to a local type.
|
||||
class MappedStreamableTypeStreamer : public TypeStreamer {
|
||||
public:
|
||||
|
||||
MappedStreamableTypeStreamer(const TypeStreamer* baseStreamer, const QVector<StreamerIndexPair>& fields);
|
||||
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
|
||||
|
||||
private:
|
||||
|
||||
const TypeStreamer* _baseStreamer;
|
||||
QVector<StreamerIndexPair> _fields;
|
||||
};
|
||||
|
||||
/// 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 QVariant read(Bitstream& in) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
QVector<StreamerNamePair> _fields;
|
||||
QByteArray _hash;
|
||||
};
|
||||
|
||||
/// Base template for collection streamers.
|
||||
template<class T> class CollectionTypeStreamer : public SimpleTypeStreamer<T> {
|
||||
};
|
||||
|
@ -1013,7 +1117,8 @@ template<class T> class CollectionTypeStreamer : public SimpleTypeStreamer<T> {
|
|||
template<class T> class CollectionTypeStreamer<QList<T> > : public SimpleTypeStreamer<QList<T> > {
|
||||
public:
|
||||
|
||||
virtual TypeReader::Type getReaderType() const { return TypeReader::LIST_TYPE; }
|
||||
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 {
|
||||
static_cast<QList<T>*>(object.data())->append(value.value<T>()); }
|
||||
|
@ -1029,7 +1134,8 @@ public:
|
|||
template<class T> class CollectionTypeStreamer<QVector<T> > : public SimpleTypeStreamer<QVector<T> > {
|
||||
public:
|
||||
|
||||
virtual TypeReader::Type getReaderType() const { return TypeReader::LIST_TYPE; }
|
||||
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 {
|
||||
static_cast<QVector<T>*>(object.data())->append(value.value<T>()); }
|
||||
|
@ -1041,11 +1147,43 @@ public:
|
|||
static_cast<QVector<T>*>(object.data())->replace(index, value.value<T>()); }
|
||||
};
|
||||
|
||||
/// A streamer for lists that maps to a local type.
|
||||
class MappedListTypeStreamer : public TypeStreamer {
|
||||
public:
|
||||
|
||||
MappedListTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer);
|
||||
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
|
||||
|
||||
protected:
|
||||
|
||||
const TypeStreamer* _baseStreamer;
|
||||
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 QVariant read(Bitstream& in) 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 TypeReader::Type getReaderType() const { return TypeReader::SET_TYPE; }
|
||||
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 {
|
||||
static_cast<QSet<T>*>(object.data())->insert(value.value<T>()); }
|
||||
|
@ -1053,11 +1191,30 @@ public:
|
|||
return static_cast<QSet<T>*>(object.data())->remove(key.value<T>()); }
|
||||
};
|
||||
|
||||
/// A streamer for sets that maps to a local type.
|
||||
class MappedSetTypeStreamer : public MappedListTypeStreamer {
|
||||
public:
|
||||
|
||||
MappedSetTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer);
|
||||
|
||||
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 TypeReader::Type getReaderType() const { return TypeReader::MAP_TYPE; }
|
||||
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>()); }
|
||||
virtual void insert(QVariant& object, const QVariant& key, const QVariant& value) const {
|
||||
|
@ -1068,6 +1225,48 @@ public:
|
|||
return QVariant::fromValue(static_cast<const QHash<K, V>*>(object.constData())->value(key.value<K>())); }
|
||||
};
|
||||
|
||||
/// A streamer for maps that maps to a local type.
|
||||
class MappedMapTypeStreamer : public TypeStreamer {
|
||||
public:
|
||||
|
||||
MappedMapTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& keyStreamer,
|
||||
const TypeStreamerPointer& valueStreamer);
|
||||
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
|
||||
|
||||
private:
|
||||
|
||||
const TypeStreamer* _baseStreamer;
|
||||
TypeStreamerPointer _keyStreamer;
|
||||
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 QVariant read(Bitstream& in) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
TypeStreamerPointer _keyStreamer;
|
||||
TypeStreamerPointer _valueStreamer;
|
||||
};
|
||||
|
||||
/// A streamer class for generic values.
|
||||
class GenericValueStreamer : public SimpleTypeStreamer<GenericValue> {
|
||||
public:
|
||||
|
||||
virtual void writeVariant(Bitstream& out, const QVariant& value) const;
|
||||
};
|
||||
|
||||
/// Macro for registering simple type streamers.
|
||||
#define REGISTER_SIMPLE_TYPE_STREAMER(X) static int X##Streamer = \
|
||||
Bitstream::registerTypeStreamer(qMetaTypeId<X>(), new SimpleTypeStreamer<X>());
|
||||
|
|
|
@ -90,6 +90,7 @@ bool operator==(const QScriptValue& first, const QScriptValue& second) {
|
|||
return true;
|
||||
|
||||
} else {
|
||||
// if none of the above tests apply, first must be invalid
|
||||
return !second.isValid();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,11 @@ SharedObject::SharedObject() :
|
|||
_weakHash.insert(_id, this);
|
||||
}
|
||||
|
||||
void SharedObject::setID(int id) {
|
||||
_weakHash.remove(_id);
|
||||
_weakHash.insert(_id = id, this);
|
||||
}
|
||||
|
||||
void SharedObject::incrementReferenceCount() {
|
||||
_referenceCount.ref();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ public:
|
|||
/// Returns the unique local ID for this object.
|
||||
int getID() const { return _id; }
|
||||
|
||||
void setID(int id);
|
||||
|
||||
/// Returns the local origin ID for this object.
|
||||
int getOriginID() const { return _originID; }
|
||||
|
||||
|
|
|
@ -214,6 +214,35 @@ static bool testSerialization(Bitstream::MetadataType metadataType) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// go back to the beginning and read everything as generics
|
||||
inStream.device()->seek(0);
|
||||
Bitstream genericIn(inStream, metadataType, Bitstream::ALL_GENERICS);
|
||||
genericIn >> testObjectReadA;
|
||||
genericIn >> testObjectReadB;
|
||||
genericIn >> messageRead;
|
||||
genericIn >> endRead;
|
||||
|
||||
// reassign the ids
|
||||
testObjectReadA->setID(testObjectWrittenA->getID());
|
||||
testObjectReadA->setOriginID(testObjectWrittenA->getOriginID());
|
||||
testObjectReadB->setID(testObjectWrittenB->getID());
|
||||
testObjectReadB->setOriginID(testObjectWrittenB->getOriginID());
|
||||
|
||||
// write it back out and compare
|
||||
QByteArray compareArray;
|
||||
QDataStream compareOutStream(&compareArray, QIODevice::WriteOnly);
|
||||
Bitstream compareOut(compareOutStream, metadataType);
|
||||
compareOut << testObjectReadA;
|
||||
compareOut << testObjectReadB;
|
||||
compareOut << messageRead;
|
||||
compareOut << endRead;
|
||||
compareOut.flush();
|
||||
|
||||
if (array != compareArray) {
|
||||
qDebug() << "Mismatch between written/generic written streams.";
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue