mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +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;
|
||||
}
|
||||
|
||||
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,
|
||||
const PropertyReaderVector& properties) :
|
||||
_className(className),
|
||||
|
@ -1713,6 +1860,19 @@ MetaField::MetaField(const QByteArray& name, const TypeStreamer* 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() {
|
||||
}
|
||||
|
||||
|
@ -2069,19 +2229,6 @@ TypeStreamer::Category GenericEnumTypeStreamer::getCategory() const {
|
|||
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,
|
||||
const QVector<StreamerIndexPair>& fields) :
|
||||
_baseStreamer(baseStreamer),
|
||||
|
@ -2334,3 +2481,7 @@ QVariant GenericMapTypeStreamer::read(Bitstream& in) const {
|
|||
TypeStreamer::Category GenericMapTypeStreamer::getCategory() const {
|
||||
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 GenericValue;
|
||||
class ObjectReader;
|
||||
class ObjectStreamer;
|
||||
class OwnedAttributeValue;
|
||||
class PropertyReader;
|
||||
class PropertyWriter;
|
||||
|
@ -46,6 +47,8 @@ typedef SharedObjectPointerTemplate<Attribute> AttributePointer;
|
|||
|
||||
typedef QPair<QByteArray, QByteArray> ScopeNamePair;
|
||||
typedef QPair<QByteArray, int> NameIntPair;
|
||||
typedef QSharedPointer<ObjectStreamer> ObjectStreamerPointer;
|
||||
typedef QWeakPointer<ObjectStreamer> WeakObjectStreamerPointer;
|
||||
typedef QSharedPointer<TypeStreamer> TypeStreamerPointer;
|
||||
typedef QWeakPointer<TypeStreamer> WeakTypeStreamerPointer;
|
||||
typedef QVector<PropertyReader> PropertyReaderVector;
|
||||
|
@ -766,6 +769,68 @@ template<class K, class V> inline Bitstream& Bitstream::operator>>(QHash<K, V>&
|
|||
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.
|
||||
class ObjectReader {
|
||||
public:
|
||||
|
@ -849,6 +914,44 @@ 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:
|
||||
|
@ -1012,32 +1115,6 @@ private:
|
|||
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.
|
||||
template<class T> class StreamableTypeStreamer : public SimpleTypeStreamer<T> {
|
||||
public:
|
||||
|
@ -1068,8 +1145,6 @@ private:
|
|||
QVector<StreamerIndexPair> _fields;
|
||||
};
|
||||
|
||||
typedef QPair<TypeStreamerPointer, QByteArray> StreamerNamePair;
|
||||
|
||||
/// A streamer for generic enums.
|
||||
class GenericStreamableTypeStreamer : public GenericTypeStreamer {
|
||||
public:
|
||||
|
@ -1238,6 +1313,13 @@ private:
|
|||
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.
|
||||
#define REGISTER_SIMPLE_TYPE_STREAMER(X) static int X##Streamer = \
|
||||
Bitstream::registerTypeStreamer(qMetaTypeId<X>(), new SimpleTypeStreamer<X>());
|
||||
|
|
Loading…
Reference in a new issue