mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 07:57:30 +02:00
Midpoint on generic object streaming.
This commit is contained in:
parent
056db4ba7d
commit
b4bd774789
2 changed files with 274 additions and 41 deletions
|
@ -1639,6 +1639,153 @@ QHash<const QMetaObject*, PropertyWriterVector> Bitstream::createPropertyWriters
|
||||||
return propertyWriters;
|
return propertyWriters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MappedObjectStreamer::MappedObjectStreamer(const QVector<StreamerPropertyPair>& properties) :
|
||||||
|
_properties(properties) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* MappedObjectStreamer::getName() const {
|
||||||
|
return _metaObject->className();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MappedObjectStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||||
|
out << _properties.size();
|
||||||
|
if (_properties.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||||
|
foreach (const StreamerPropertyPair& property, _properties) {
|
||||||
|
out << property.first.data();
|
||||||
|
if (full) {
|
||||||
|
out << QByteArray::fromRawData(property.second.name(), strlen(property.second.name()));
|
||||||
|
} else {
|
||||||
|
hash.addData(property.second.name(), strlen(property.second.name()) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!full) {
|
||||||
|
QByteArray hashResult = hash.result();
|
||||||
|
out.write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MappedObjectStreamer::write(Bitstream& out, QObject* object) const {
|
||||||
|
foreach (const StreamerPropertyPair& property, _properties) {
|
||||||
|
property.first->write(out, property.second.read(object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MappedObjectStreamer::writeDelta(Bitstream& out, QObject* object, QObject* reference) const {
|
||||||
|
foreach (const StreamerPropertyPair& property, _properties) {
|
||||||
|
property.first->writeDelta(out, property.second.read(object), (reference && reference->metaObject() == _metaObject) ?
|
||||||
|
property.second.read(reference) : QVariant());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* MappedObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||||
|
if (!object && _metaObject) {
|
||||||
|
object = _metaObject->newInstance();
|
||||||
|
}
|
||||||
|
foreach (const StreamerPropertyPair& property, _properties) {
|
||||||
|
QVariant value = property.first->read(in);
|
||||||
|
if (property.second.isValid() && object) {
|
||||||
|
property.second.write(object, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* MappedObjectStreamer::readDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||||
|
if (!object && _metaObject) {
|
||||||
|
object = _metaObject->newInstance();
|
||||||
|
}
|
||||||
|
foreach (const StreamerPropertyPair& property, _properties) {
|
||||||
|
QVariant value;
|
||||||
|
property.first->readDelta(in, value, (property.second.isValid() && reference) ?
|
||||||
|
property.second.read(reference) : QVariant());
|
||||||
|
if (property.second.isValid() && object) {
|
||||||
|
property.second.write(object, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericObjectStreamer::GenericObjectStreamer(const QByteArray& name, const QVector<StreamerNamePair>& properties,
|
||||||
|
const QByteArray& hash) :
|
||||||
|
_name(name),
|
||||||
|
_properties(properties),
|
||||||
|
_hash(hash) {
|
||||||
|
|
||||||
|
_metaObject = &GenericSharedObject::staticMetaObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GenericObjectStreamer::getName() const {
|
||||||
|
return _name.constData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenericObjectStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||||
|
out << _properties.size();
|
||||||
|
if (_properties.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (const StreamerNamePair& property, _properties) {
|
||||||
|
out << property.first.data();
|
||||||
|
if (full) {
|
||||||
|
out << property.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!full) {
|
||||||
|
if (_hash.isEmpty()) {
|
||||||
|
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||||
|
foreach (const StreamerNamePair& property, _properties) {
|
||||||
|
hash.addData(property.second.constData(), property.second.size() + 1);
|
||||||
|
}
|
||||||
|
const_cast<GenericObjectStreamer*>(this)->_hash = hash.result();
|
||||||
|
}
|
||||||
|
out.write(_hash.constData(), _hash.size() * BITS_IN_BYTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenericObjectStreamer::write(Bitstream& out, QObject* object) const {
|
||||||
|
const QVariantList& values = static_cast<GenericSharedObject*>(object)->getValues();
|
||||||
|
for (int i = 0; i < _properties.size(); i++) {
|
||||||
|
_properties.at(i).first->write(out, values.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenericObjectStreamer::writeDelta(Bitstream& out, QObject* object, QObject* reference) const {
|
||||||
|
for (int i = 0; i < _properties.size(); i++) {
|
||||||
|
_properties.at(i).first->writeDelta(out, static_cast<GenericSharedObject*>(object)->getValues().at(i), reference ?
|
||||||
|
static_cast<GenericSharedObject*>(reference)->getValues().at(i) : QVariant());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||||
|
if (!object) {
|
||||||
|
object = new GenericSharedObject(_weakSelf);
|
||||||
|
}
|
||||||
|
QVariantList values;
|
||||||
|
foreach (const StreamerNamePair& property, _properties) {
|
||||||
|
values.append(property.first->read(in));
|
||||||
|
}
|
||||||
|
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* GenericObjectStreamer::readDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||||
|
if (!object) {
|
||||||
|
object = new GenericSharedObject(_weakSelf);
|
||||||
|
}
|
||||||
|
QVariantList values;
|
||||||
|
for (int i = 0; i < _properties.size(); i++) {
|
||||||
|
const StreamerNamePair& property = _properties.at(i);
|
||||||
|
QVariant value;
|
||||||
|
property.first->readDelta(in, value, reference ?
|
||||||
|
static_cast<const GenericSharedObject*>(reference)->getValues().at(i) : QVariant());
|
||||||
|
values.append(value);
|
||||||
|
}
|
||||||
|
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectReader::ObjectReader(const QByteArray& className, const QMetaObject* metaObject,
|
ObjectReader::ObjectReader(const QByteArray& className, const QMetaObject* metaObject,
|
||||||
const PropertyReaderVector& properties) :
|
const PropertyReaderVector& properties) :
|
||||||
_className(className),
|
_className(className),
|
||||||
|
@ -1713,6 +1860,19 @@ MetaField::MetaField(const QByteArray& name, const TypeStreamer* streamer) :
|
||||||
_streamer(streamer) {
|
_streamer(streamer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenericValue::GenericValue(const TypeStreamerPointer& streamer, const QVariant& value) :
|
||||||
|
_streamer(streamer),
|
||||||
|
_value(value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GenericValue::operator==(const GenericValue& other) const {
|
||||||
|
return _streamer == other._streamer && _value == other._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericSharedObject::GenericSharedObject(const ObjectStreamerPointer& streamer) :
|
||||||
|
_streamer(streamer) {
|
||||||
|
}
|
||||||
|
|
||||||
TypeStreamer::~TypeStreamer() {
|
TypeStreamer::~TypeStreamer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2069,19 +2229,6 @@ TypeStreamer::Category GenericEnumTypeStreamer::getCategory() const {
|
||||||
return ENUM_CATEGORY;
|
return ENUM_CATEGORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericValue::GenericValue(const TypeStreamerPointer& streamer, const QVariant& value) :
|
|
||||||
_streamer(streamer),
|
|
||||||
_value(value) {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GenericValue::operator==(const GenericValue& other) const {
|
|
||||||
return _streamer == other._streamer && _value == other._value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TypeStreamer* GenericValueStreamer::getStreamerToWrite(const QVariant& value) const {
|
|
||||||
return value.value<GenericValue>().getStreamer().data();
|
|
||||||
}
|
|
||||||
|
|
||||||
MappedStreamableTypeStreamer::MappedStreamableTypeStreamer(const TypeStreamer* baseStreamer,
|
MappedStreamableTypeStreamer::MappedStreamableTypeStreamer(const TypeStreamer* baseStreamer,
|
||||||
const QVector<StreamerIndexPair>& fields) :
|
const QVector<StreamerIndexPair>& fields) :
|
||||||
_baseStreamer(baseStreamer),
|
_baseStreamer(baseStreamer),
|
||||||
|
@ -2334,3 +2481,7 @@ QVariant GenericMapTypeStreamer::read(Bitstream& in) const {
|
||||||
TypeStreamer::Category GenericMapTypeStreamer::getCategory() const {
|
TypeStreamer::Category GenericMapTypeStreamer::getCategory() const {
|
||||||
return MAP_CATEGORY;
|
return MAP_CATEGORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TypeStreamer* GenericValueStreamer::getStreamerToWrite(const QVariant& value) const {
|
||||||
|
return value.value<GenericValue>().getStreamer().data();
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ class AttributeValue;
|
||||||
class Bitstream;
|
class Bitstream;
|
||||||
class GenericValue;
|
class GenericValue;
|
||||||
class ObjectReader;
|
class ObjectReader;
|
||||||
|
class ObjectStreamer;
|
||||||
class OwnedAttributeValue;
|
class OwnedAttributeValue;
|
||||||
class PropertyReader;
|
class PropertyReader;
|
||||||
class PropertyWriter;
|
class PropertyWriter;
|
||||||
|
@ -46,6 +47,8 @@ typedef SharedObjectPointerTemplate<Attribute> AttributePointer;
|
||||||
|
|
||||||
typedef QPair<QByteArray, QByteArray> ScopeNamePair;
|
typedef QPair<QByteArray, QByteArray> ScopeNamePair;
|
||||||
typedef QPair<QByteArray, int> NameIntPair;
|
typedef QPair<QByteArray, int> NameIntPair;
|
||||||
|
typedef QSharedPointer<ObjectStreamer> ObjectStreamerPointer;
|
||||||
|
typedef QWeakPointer<ObjectStreamer> WeakObjectStreamerPointer;
|
||||||
typedef QSharedPointer<TypeStreamer> TypeStreamerPointer;
|
typedef QSharedPointer<TypeStreamer> TypeStreamerPointer;
|
||||||
typedef QWeakPointer<TypeStreamer> WeakTypeStreamerPointer;
|
typedef QWeakPointer<TypeStreamer> WeakTypeStreamerPointer;
|
||||||
typedef QVector<PropertyReader> PropertyReaderVector;
|
typedef QVector<PropertyReader> PropertyReaderVector;
|
||||||
|
@ -766,6 +769,68 @@ template<class K, class V> inline Bitstream& Bitstream::operator>>(QHash<K, V>&
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Contains the information required to stream an object.
|
||||||
|
class ObjectStreamer {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual const char* getName() const = 0;
|
||||||
|
virtual void writeMetadata(Bitstream& out, bool full) const = 0;
|
||||||
|
virtual void write(Bitstream& out, QObject* object) const = 0;
|
||||||
|
virtual void writeDelta(Bitstream& out, QObject* object, QObject* reference) const = 0;
|
||||||
|
virtual QObject* read(Bitstream& in, QObject* object = NULL) const = 0;
|
||||||
|
virtual QObject* readDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const QMetaObject* _metaObject;
|
||||||
|
ObjectStreamerPointer _self;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QPair<TypeStreamerPointer, QMetaProperty> StreamerPropertyPair;
|
||||||
|
|
||||||
|
/// A streamer that maps to a local class.
|
||||||
|
class MappedObjectStreamer : public ObjectStreamer {
|
||||||
|
public:
|
||||||
|
|
||||||
|
MappedObjectStreamer(const QVector<StreamerPropertyPair>& properties);
|
||||||
|
|
||||||
|
virtual const char* getName() const;
|
||||||
|
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||||
|
virtual void write(Bitstream& out, QObject* object) const;
|
||||||
|
virtual void writeDelta(Bitstream& out, QObject* object, QObject* reference) const;
|
||||||
|
virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
|
||||||
|
virtual QObject* readDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
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, QObject* object) const;
|
||||||
|
virtual void writeDelta(Bitstream& out, QObject* object, QObject* reference) const;
|
||||||
|
virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
|
||||||
|
virtual QObject* readDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
friend class Bitstream;
|
||||||
|
|
||||||
|
QByteArray _name;
|
||||||
|
WeakObjectStreamerPointer _weakSelf;
|
||||||
|
QVector<StreamerNamePair> _properties;
|
||||||
|
QByteArray _hash;
|
||||||
|
};
|
||||||
|
|
||||||
/// Contains the information required to read an object from the stream.
|
/// Contains the information required to read an object from the stream.
|
||||||
class ObjectReader {
|
class ObjectReader {
|
||||||
public:
|
public:
|
||||||
|
@ -849,6 +914,44 @@ Q_DECLARE_METATYPE(const QMetaObject*)
|
||||||
/// Macro for registering streamable meta-objects.
|
/// Macro for registering streamable meta-objects.
|
||||||
#define REGISTER_META_OBJECT(x) static int x##Registration = Bitstream::registerMetaObject(#x, &x::staticMetaObject);
|
#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.
|
/// Interface for objects that can write values to and read values from bitstreams.
|
||||||
class TypeStreamer {
|
class TypeStreamer {
|
||||||
public:
|
public:
|
||||||
|
@ -1012,32 +1115,6 @@ private:
|
||||||
QByteArray _hash;
|
QByteArray _hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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)
|
|
||||||
|
|
||||||
/// A streamer class for generic values.
|
|
||||||
class GenericValueStreamer : public SimpleTypeStreamer<GenericValue> {
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual const TypeStreamer* getStreamerToWrite(const QVariant& value) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A streamer for types compiled by mtc.
|
/// A streamer for types compiled by mtc.
|
||||||
template<class T> class StreamableTypeStreamer : public SimpleTypeStreamer<T> {
|
template<class T> class StreamableTypeStreamer : public SimpleTypeStreamer<T> {
|
||||||
public:
|
public:
|
||||||
|
@ -1068,8 +1145,6 @@ private:
|
||||||
QVector<StreamerIndexPair> _fields;
|
QVector<StreamerIndexPair> _fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QPair<TypeStreamerPointer, QByteArray> StreamerNamePair;
|
|
||||||
|
|
||||||
/// A streamer for generic enums.
|
/// A streamer for generic enums.
|
||||||
class GenericStreamableTypeStreamer : public GenericTypeStreamer {
|
class GenericStreamableTypeStreamer : public GenericTypeStreamer {
|
||||||
public:
|
public:
|
||||||
|
@ -1238,6 +1313,13 @@ private:
|
||||||
TypeStreamerPointer _valueStreamer;
|
TypeStreamerPointer _valueStreamer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A streamer class for generic values.
|
||||||
|
class GenericValueStreamer : public SimpleTypeStreamer<GenericValue> {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual const TypeStreamer* getStreamerToWrite(const QVariant& value) const;
|
||||||
|
};
|
||||||
|
|
||||||
/// Macro for registering simple type streamers.
|
/// Macro for registering simple type streamers.
|
||||||
#define REGISTER_SIMPLE_TYPE_STREAMER(X) static int X##Streamer = \
|
#define REGISTER_SIMPLE_TYPE_STREAMER(X) static int X##Streamer = \
|
||||||
Bitstream::registerTypeStreamer(qMetaTypeId<X>(), new SimpleTypeStreamer<X>());
|
Bitstream::registerTypeStreamer(qMetaTypeId<X>(), new SimpleTypeStreamer<X>());
|
||||||
|
|
Loading…
Reference in a new issue