From b4bd774789a310a6570ee025e4f454542775e47b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 12 Jun 2014 16:22:32 -0700 Subject: [PATCH] Midpoint on generic object streaming. --- libraries/metavoxels/src/Bitstream.cpp | 177 +++++++++++++++++++++++-- libraries/metavoxels/src/Bitstream.h | 138 +++++++++++++++---- 2 files changed, 274 insertions(+), 41 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index d285e4aa3f..f1c927451b 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -1639,6 +1639,153 @@ QHash Bitstream::createPropertyWriters return propertyWriters; } +MappedObjectStreamer::MappedObjectStreamer(const QVector& 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& 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(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(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(object)->getValues().at(i), reference ? + static_cast(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(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(reference)->getValues().at(i) : QVariant()); + values.append(value); + } + static_cast(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().getStreamer().data(); -} - MappedStreamableTypeStreamer::MappedStreamableTypeStreamer(const TypeStreamer* baseStreamer, const QVector& 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().getStreamer().data(); +} diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index ee9b8b472c..07e4b94568 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -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 AttributePointer; typedef QPair ScopeNamePair; typedef QPair NameIntPair; +typedef QSharedPointer ObjectStreamerPointer; +typedef QWeakPointer WeakObjectStreamerPointer; typedef QSharedPointer TypeStreamerPointer; typedef QWeakPointer WeakTypeStreamerPointer; typedef QVector PropertyReaderVector; @@ -766,6 +769,68 @@ template inline Bitstream& Bitstream::operator>>(QHash& 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 StreamerPropertyPair; + +/// A streamer that maps to a local class. +class MappedObjectStreamer : public ObjectStreamer { +public: + + MappedObjectStreamer(const QVector& 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 _properties; +}; + +typedef QPair StreamerNamePair; + +/// A streamer for generic objects. +class GenericObjectStreamer : public ObjectStreamer { +public: + + GenericObjectStreamer(const QByteArray& name, const QVector& 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 _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 { -public: - - virtual const TypeStreamer* getStreamerToWrite(const QVariant& value) const; -}; - /// A streamer for types compiled by mtc. template class StreamableTypeStreamer : public SimpleTypeStreamer { public: @@ -1068,8 +1145,6 @@ private: QVector _fields; }; -typedef QPair 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 { +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(), new SimpleTypeStreamer());