More streaming work.

This commit is contained in:
Andrzej Kapolka 2013-12-19 16:53:38 -08:00
parent de175e97b6
commit b7f0057fe9
5 changed files with 142 additions and 34 deletions

View file

@ -11,7 +11,12 @@
#include "AttributeRegistry.h"
#include "MetavoxelData.h"
AttributeRegistry AttributeRegistry::_instance;
REGISTER_META_OBJECT(QRgbAttribute)
AttributeRegistry* AttributeRegistry::getInstance() {
static AttributeRegistry registry;
return &registry;
}
AttributeRegistry::AttributeRegistry() :
_guideAttribute(registerAttribute(new PolymorphicAttribute("guide", PolymorphicDataPointer(new DefaultMetavoxelGuide())))),
@ -36,7 +41,7 @@ AttributePointer AttributeRegistry::registerAttribute(AttributePointer attribute
}
QScriptValue AttributeRegistry::getAttribute(QScriptContext* context, QScriptEngine* engine) {
return engine->newQObject(_instance.getAttribute(context->argument(0).toString()).data(), QScriptEngine::QtOwnership,
return engine->newQObject(getInstance()->getAttribute(context->argument(0).toString()).data(), QScriptEngine::QtOwnership,
QScriptEngine::PreferExistingWrapperObject);
}

View file

@ -32,7 +32,7 @@ class AttributeRegistry {
public:
/// Returns a pointer to the singleton registry instance.
static AttributeRegistry* getInstance() { return &_instance; }
static AttributeRegistry* getInstance();
AttributeRegistry();
@ -65,8 +65,6 @@ private:
static QScriptValue getAttribute(QScriptContext* context, QScriptEngine* engine);
static AttributeRegistry _instance;
QHash<QString, AttributePointer> _attributes;
AttributePointer _guideAttribute;
AttributePointer _colorAttribute;
@ -170,7 +168,7 @@ public:
virtual void* getDefaultValue() const { return encodeInline(_defaultValue); }
private:
protected:
T _defaultValue;
};
@ -211,9 +209,12 @@ template<class T, int bits> inline bool SimpleInlineAttribute<T, bits>::merge(vo
/// Provides appropriate averaging for RGBA values.
class QRgbAttribute : public InlineAttribute<QRgb> {
Q_OBJECT
Q_PROPERTY(int defaultValue MEMBER _defaultValue)
public:
QRgbAttribute(const QString& name, QRgb defaultValue = QRgb());
Q_INVOKABLE QRgbAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
virtual bool merge(void*& parent, void* children[]) const;

View file

@ -12,21 +12,30 @@
#include <QMetaProperty>
#include <QtDebug>
#include "AttributeRegistry.h"
#include "Bitstream.h"
QHash<QByteArray, const QMetaObject*> Bitstream::_metaObjects;
QHash<int, TypeStreamer*> Bitstream::_typeStreamers;
REGISTER_SIMPLE_TYPE_STREAMER(QByteArray)
REGISTER_SIMPLE_TYPE_STREAMER(QString)
REGISTER_SIMPLE_TYPE_STREAMER(bool)
REGISTER_SIMPLE_TYPE_STREAMER(int)
void Bitstream::registerMetaObject(const QByteArray& name, const QMetaObject* metaObject) {
_metaObjects.insert(name, metaObject);
int Bitstream::registerMetaObject(const char* className, const QMetaObject* metaObject) {
getMetaObjects().insert(className, metaObject);
return 0;
}
void Bitstream::registerTypeStreamer(int type, TypeStreamer* streamer) {
_typeStreamers.insert(type, streamer);
int Bitstream::registerTypeStreamer(int type, TypeStreamer* streamer) {
getTypeStreamers().insert(type, streamer);
return 0;
}
Bitstream::Bitstream(QDataStream& underlying) :
_underlying(underlying), _byte(0), _position(0), _classNameStreamer(*this) {
_underlying(underlying),
_byte(0),
_position(0),
_classNameStreamer(*this),
_attributeStreamer(*this) {
}
const int BITS_IN_BYTE = 8;
@ -94,37 +103,63 @@ Bitstream& Bitstream::operator>>(bool& value) {
return *this;
}
Bitstream& Bitstream::operator<<(qint32 value) {
Bitstream& Bitstream::operator<<(int value) {
return write(&value, 32);
}
Bitstream& Bitstream::operator>>(qint32& value) {
return read(&value, 32);
Bitstream& Bitstream::operator>>(int& value) {
qint32 sizedValue;
read(&sizedValue, 32);
value = sizedValue;
return *this;
}
Bitstream& Bitstream::operator<<(const QByteArray& string) {
*this << (qint32)string.size();
*this << string.size();
return write(string.constData(), string.size() * BITS_IN_BYTE);
}
Bitstream& Bitstream::operator>>(QByteArray& string) {
qint32 size;
int size;
*this >> size;
return read(string.data(), size * BITS_IN_BYTE);
}
Bitstream& Bitstream::operator<<(const QString& string) {
*this << (qint32)string.size();
*this << string.size();
return write(string.constData(), string.size() * sizeof(QChar) * BITS_IN_BYTE);
}
Bitstream& Bitstream::operator>>(QString& string) {
qint32 size;
int size;
*this >> size;
return read(string.data(), size * sizeof(QChar) * BITS_IN_BYTE);
}
Bitstream& Bitstream::operator<<(const QVariant& value) {
*this << value.userType();
TypeStreamer* streamer = getTypeStreamers().value(value.userType());
if (streamer) {
streamer->write(*this, value);
}
return *this;
}
Bitstream& Bitstream::operator>>(QVariant& value) {
int type;
*this >> type;
TypeStreamer* streamer = getTypeStreamers().value(type);
if (streamer) {
value = streamer->read(*this);
}
return *this;
}
Bitstream& Bitstream::operator<<(QObject* object) {
if (!object) {
_classNameStreamer << QByteArray();
return *this;
}
const QMetaObject* metaObject = object->metaObject();
_classNameStreamer << QByteArray::fromRawData(metaObject->className(), strlen(metaObject->className()));
for (int i = 0; i < metaObject->propertyCount(); i++) {
@ -132,7 +167,7 @@ Bitstream& Bitstream::operator<<(QObject* object) {
if (!property.isStored(object)) {
continue;
}
TypeStreamer* streamer = _typeStreamers.value(property.userType());
TypeStreamer* streamer = getTypeStreamers().value(property.userType());
if (streamer) {
streamer->write(*this, property.read(object));
}
@ -143,7 +178,11 @@ Bitstream& Bitstream::operator<<(QObject* object) {
Bitstream& Bitstream::operator>>(QObject*& object) {
QByteArray className;
_classNameStreamer >> className;
const QMetaObject* metaObject = _metaObjects.value(className);
if (className.isEmpty()) {
object = NULL;
return *this;
}
const QMetaObject* metaObject = getMetaObjects().value(className);
if (metaObject) {
object = metaObject->newInstance();
for (int i = 0; i < metaObject->propertyCount(); i++) {
@ -151,7 +190,7 @@ Bitstream& Bitstream::operator>>(QObject*& object) {
if (!property.isStored(object)) {
continue;
}
TypeStreamer* streamer = _typeStreamers.value(property.userType());
TypeStreamer* streamer = getTypeStreamers().value(property.userType());
if (streamer) {
property.write(object, streamer->read(*this));
}
@ -162,6 +201,27 @@ Bitstream& Bitstream::operator>>(QObject*& object) {
return *this;
}
Bitstream& Bitstream::operator<<(const AttributePointer& attribute) {
return *this << (QObject*)attribute.data();
}
Bitstream& Bitstream::operator>>(AttributePointer& attribute) {
QObject* object;
*this >> object;
attribute = AttributeRegistry::getInstance()->registerAttribute(static_cast<Attribute*>(object));
return *this;
}
QHash<QByteArray, const QMetaObject*>& Bitstream::getMetaObjects() {
static QHash<QByteArray, const QMetaObject*> metaObjects;
return metaObjects;
}
QHash<int, TypeStreamer*>& Bitstream::getTypeStreamers() {
static QHash<int, TypeStreamer*> typeStreamers;
return typeStreamers;
}
IDStreamer::IDStreamer(Bitstream& stream) :
_stream(stream),
_bits(1) {

View file

@ -10,6 +10,8 @@
#define __interface__Bitstream__
#include <QHash>
#include <QMetaType>
#include <QSharedPointer>
#include <QVariant>
class QByteArray;
@ -17,9 +19,12 @@ class QDataStream;
class QMetaObject;
class QObject;
class Attribute;
class Bitstream;
class TypeStreamer;
typedef QSharedPointer<Attribute> AttributePointer;
/// 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
/// us to use the minimum number of bits to encode the IDs.
@ -87,10 +92,12 @@ class Bitstream {
public:
/// Registers a metaobject under its name so that instances of it can be streamed.
static void registerMetaObject(const QByteArray& name, const QMetaObject* metaObject);
/// \return zero; the function only returns a value so that it can be used in static initialization
static int registerMetaObject(const char* className, const QMetaObject* metaObject);
/// Registers a streamer for the specified Qt-registered type.
static void registerTypeStreamer(int type, TypeStreamer* streamer);
/// \return zero; the function only returns a value so that it can be used in static initialization
static int registerTypeStreamer(int type, TypeStreamer* streamer);
/// Creates a new bitstream. Note: the stream may be used for reading or writing, but not both.
Bitstream(QDataStream& underlying);
@ -108,11 +115,14 @@ public:
/// Flushes any unwritten bits to the underlying stream.
void flush();
/// Returns a reference to the attribute streamer.
RepeatedValueStreamer<AttributePointer>& getAttributeStreamer() { return _attributeStreamer; }
Bitstream& operator<<(bool value);
Bitstream& operator>>(bool& value);
Bitstream& operator<<(qint32 value);
Bitstream& operator>>(qint32& value);
Bitstream& operator<<(int value);
Bitstream& operator>>(int& value);
Bitstream& operator<<(const QByteArray& string);
Bitstream& operator>>(QByteArray& string);
@ -120,9 +130,15 @@ public:
Bitstream& operator<<(const QString& string);
Bitstream& operator>>(QString& string);
Bitstream& operator<<(const QVariant& value);
Bitstream& operator>>(QVariant& value);
Bitstream& operator<<(QObject* object);
Bitstream& operator>>(QObject*& object);
Bitstream& operator<<(const AttributePointer& attribute);
Bitstream& operator>>(AttributePointer& attribute);
private:
QDataStream& _underlying;
@ -130,11 +146,15 @@ private:
int _position;
RepeatedValueStreamer<QByteArray> _classNameStreamer;
RepeatedValueStreamer<AttributePointer> _attributeStreamer;
static QHash<QByteArray, const QMetaObject*> _metaObjects;
static QHash<int, TypeStreamer*> _typeStreamers;
static QHash<QByteArray, const QMetaObject*>& getMetaObjects();
static QHash<int, TypeStreamer*>& getTypeStreamers();
};
/// Macro for registering streamable meta-objects.
#define REGISTER_META_OBJECT(x) static int x##Registration = Bitstream::registerMetaObject(#x, &x::staticMetaObject);
/// Interface for objects that can write values to and read values from bitstreams.
class TypeStreamer {
public:
@ -144,11 +164,15 @@ public:
};
/// A streamer that works with Bitstream's operators.
template<class T> class SimpleTypeStreamer {
template<class T> class SimpleTypeStreamer : public TypeStreamer {
public:
virtual void write(Bitstream& out, const QVariant& value) const { out << value.value<T>(); }
virtual QVariant read(Bitstream& in) const { T value; in >> value; return QVariant::fromValue(value); }
};
/// Macro for registering simple type streamers.
#define REGISTER_SIMPLE_TYPE_STREAMER(x) static int x##Streamer = \
Bitstream::registerTypeStreamer(QMetaType::type(#x), new SimpleTypeStreamer<x>());
#endif /* defined(__interface__Bitstream__) */

View file

@ -65,17 +65,35 @@ AttributeValue MetavoxelData::getAttributeValue(const MetavoxelPath& path, const
}
void MetavoxelData::read(Bitstream& in) {
// save the old roots and clear
QHash<AttributePointer, MetavoxelNode*> oldRoots = _roots;
_roots.clear();
// read in the new roots, reusing old ones where appropriate
qint32 rootCount;
in >> rootCount;
for (int i = 0; i < rootCount; i++) {
}
AttributePointer attribute;
in.getAttributeStreamer() >> attribute;
MetavoxelNode* root = oldRoots.take(attribute);
if (!root) {
root = new MetavoxelNode(attribute);
}
_roots.insert(attribute, root);
root->read(attribute, in);
}
// clear out the remaining old roots
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = oldRoots.constBegin(); it != oldRoots.constEnd(); it++) {
it.value()->destroy(it.key());
delete it.value();
}
}
void MetavoxelData::write(Bitstream& out) const {
out << (qint32)_roots.size();
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) {
out.getAttributeStreamer() << it.key();
it.value()->write(it.key(), out);
}
}