From aac7459f42846e0c924e24a78d25c9a670b0841b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 13 Jun 2014 18:32:57 -0700 Subject: [PATCH] More work on JSON encoding. --- libraries/metavoxels/src/Bitstream.cpp | 180 +++++++++++++++++++++++- libraries/metavoxels/src/Bitstream.h | 48 ++++++- tests/metavoxels/src/MetavoxelTests.cpp | 12 ++ 3 files changed, 232 insertions(+), 8 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 1266e8efa4..aa5ed3fa5e 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -1657,6 +1657,109 @@ const TypeStreamer* Bitstream::createInvalidTypeStreamer() { return streamer; } +JSONWriter& JSONWriter::operator<<(bool value) { + _contents.append(value); + return *this; +} + +JSONWriter& JSONWriter::operator<<(int value) { + _contents.append(value); + return *this; +} + +JSONWriter& JSONWriter::operator<<(uint value) { + _contents.append((int)value); + return *this; +} + +JSONWriter& JSONWriter::operator<<(float value) { + _contents.append((double)value); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QByteArray& value) { + _contents.append(QString(value.toPercentEncoding())); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QColor& value) { + _contents.append(value.name()); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QScriptValue& value) { + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QString& value) { + _contents.append(value); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QUrl& value) { + _contents.append(value.toString()); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const glm::vec3& value) { + QJsonArray array; + array.append(value.x); + array.append(value.y); + array.append(value.z); + _contents.append(array); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const glm::quat& value) { + QJsonArray array; + array.append(value.x); + array.append(value.y); + array.append(value.z); + array.append(value.w); + _contents.append(array); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QMetaObject* metaObject) { + if (!metaObject) { + _contents.append(QJsonValue()); + return *this; + } + const ObjectStreamer* streamer = Bitstream::getObjectStreamers().value(metaObject); + addObjectStreamer(streamer); + _contents.append(QString(streamer->getName())); + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QVariant& value) { + if (!value.isValid()) { + _contents.append(QJsonValue()); + return *this; + } + const TypeStreamer* streamer = Bitstream::getTypeStreamers().value(value.userType()); + if (streamer) { + _contents.append(streamer->getJSONVariantData(*this, value)); + } else { + qWarning() << "Non-streamable type:" << value.typeName(); + } + return *this; +} + +JSONWriter& JSONWriter::operator<<(const SharedObjectPointer& object) { + if (object) { + addSharedObject(object); + _contents.append(object->getID()); + } else { + _contents.append(0); + } + return *this; +} + +JSONWriter& JSONWriter::operator<<(const QObject* object) { + _contents.append(getData(object)); + return *this; +} + void JSONWriter::addTypeStreamer(const TypeStreamer* streamer) { if (!_typeStreamerNames.contains(streamer->getName())) { _typeStreamerNames.insert(streamer->getName()); @@ -1695,11 +1798,31 @@ void JSONWriter::addSharedObject(const SharedObjectPointer& object) { QJsonObject sharedObject; sharedObject.insert("id", object->getID()); sharedObject.insert("originID", object->getOriginID()); - + sharedObject.insert("data", getData(object.data())); _sharedObjects.replace(index, sharedObject); } } +QJsonDocument JSONWriter::getDocument() const { + QJsonObject top; + top.insert("contents", _contents); + top.insert("objects", _sharedObjects); + top.insert("classes", _objectStreamers); + top.insert("types", _typeStreamers); + return QJsonDocument(top); +} + +QJsonValue JSONWriter::getData(const QObject* object) { + if (!object) { + return QJsonValue(); + } + const QMetaObject* metaObject = object->metaObject(); + const ObjectStreamer* streamer = (metaObject == &GenericSharedObject::staticMetaObject) ? + static_cast(object)->getStreamer().data() : + Bitstream::getObjectStreamers().value(metaObject); + return streamer->getJSONData(*this, object); +} + ObjectStreamer::ObjectStreamer(const QMetaObject* metaObject) : _metaObject(metaObject) { } @@ -2023,6 +2146,14 @@ QJsonValue TypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) return QJsonValue(); } +QJsonValue TypeStreamer::getJSONVariantData(JSONWriter& writer, const QVariant& value) const { + writer.addTypeStreamer(this); + QJsonObject data; + data.insert("type", QString(getName())); + data.insert("value", getJSONData(writer, value)); + return data; +} + bool TypeStreamer::equal(const QVariant& first, const QVariant& second) const { return first == second; } @@ -2208,6 +2339,10 @@ QJsonValue EnumTypeStreamer::getJSONMetadata(JSONWriter& writer) const { return metadata; } +QJsonValue EnumTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { + return value.toInt(); +} + TypeStreamer::Category EnumTypeStreamer::getCategory() const { return ENUM_CATEGORY; } @@ -2372,6 +2507,10 @@ QJsonValue GenericEnumTypeStreamer::getJSONMetadata(JSONWriter& writer) const { return metadata; } +QJsonValue GenericEnumTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { + return value.toInt(); +} + void GenericEnumTypeStreamer::write(Bitstream& out, const QVariant& value) const { int intValue = value.toInt(); out.write(&intValue, _bits); @@ -2464,6 +2603,15 @@ QJsonValue GenericStreamableTypeStreamer::getJSONMetadata(JSONWriter& writer) co return metadata; } +QJsonValue GenericStreamableTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { + QVariantList values = value.toList(); + QJsonArray array; + for (int i = 0; i < _fields.size(); i++) { + array.append(_fields.at(i).first->getJSONData(writer, values.at(i))); + } + return array; +} + void GenericStreamableTypeStreamer::write(Bitstream& out, const QVariant& value) const { QVariantList values = value.toList(); for (int i = 0; i < _fields.size(); i++) { @@ -2537,6 +2685,15 @@ QJsonValue GenericListTypeStreamer::getJSONMetadata(JSONWriter& writer) const { return metadata; } +QJsonValue GenericListTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { + QVariantList values = value.toList(); + QJsonArray array; + foreach (const QVariant& element, values) { + array.append(_valueStreamer->getJSONData(writer, element)); + } + return array; +} + void GenericListTypeStreamer::write(Bitstream& out, const QVariant& value) const { QVariantList values = value.toList(); out << values.size(); @@ -2660,6 +2817,18 @@ QJsonValue GenericMapTypeStreamer::getJSONMetadata(JSONWriter& writer) const { return metadata; } +QJsonValue GenericMapTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { + QVariantPairList values = value.value(); + QJsonArray array; + foreach (const QVariantPair& pair, values) { + QJsonArray pairArray; + pairArray.append(_keyStreamer->getJSONData(writer, pair.first)); + pairArray.append(_valueStreamer->getJSONData(writer, pair.second)); + array.append(pairArray); + } + return array; +} + void GenericMapTypeStreamer::write(Bitstream& out, const QVariant& value) const { QVariantPairList values = value.value(); out << values.size(); @@ -2685,6 +2854,15 @@ TypeStreamer::Category GenericMapTypeStreamer::getCategory() const { return MAP_CATEGORY; } +QJsonValue GenericValueStreamer::getJSONVariantData(JSONWriter& writer, const QVariant& value) const { + GenericValue genericValue = value.value(); + writer.addTypeStreamer(genericValue.getStreamer().data()); + QJsonObject data; + data.insert("type", QString(genericValue.getStreamer()->getName())); + data.insert("value", genericValue.getStreamer()->getJSONData(writer, genericValue.getValue())); + return data; +} + void GenericValueStreamer::writeVariant(Bitstream& out, const QVariant& value) const { GenericValue genericValue = value.value(); out << genericValue.getStreamer().data(); diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 732d1f8f7b..159633c810 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,7 @@ class Attribute; class AttributeValue; class Bitstream; class GenericValue; +class JSONWriter; class ObjectReader; class ObjectStreamer; class OwnedAttributeValue; @@ -447,6 +449,8 @@ private slots: private: + friend class JSONWriter; + ObjectStreamerPointer readGenericObjectStreamer(const QByteArray& name); TypeStreamerPointer readGenericTypeStreamer(const QByteArray& name, int category); @@ -771,21 +775,44 @@ template inline Bitstream& Bitstream::operator>>(QHash& /// Tracks state when writing to JSON. class JSONWriter { public: - - void addTypeStreamer(const TypeStreamer* streamer); - void addObjectStreamer(const ObjectStreamer* streamer); + + JSONWriter& operator<<(bool value); + JSONWriter& operator<<(int value); + JSONWriter& operator<<(uint value); + JSONWriter& operator<<(float value); + JSONWriter& operator<<(const QByteArray& value); + JSONWriter& operator<<(const QColor& value); + JSONWriter& operator<<(const QScriptValue& value); + JSONWriter& operator<<(const QString& value); + JSONWriter& operator<<(const QUrl& value); + JSONWriter& operator<<(const glm::vec3& value); + JSONWriter& operator<<(const glm::quat& value); + JSONWriter& operator<<(const QMetaObject* metaObject); + + JSONWriter& operator<<(const QVariant& value); + JSONWriter& operator<<(const SharedObjectPointer& object); + JSONWriter& operator<<(const QObject* object); + void addSharedObject(const SharedObjectPointer& object); + void addObjectStreamer(const ObjectStreamer* streamer); + void addTypeStreamer(const TypeStreamer* streamer); + + QJsonDocument getDocument() const; private: - QSet _typeStreamerNames; - QJsonArray _typeStreamers; + QJsonValue getData(const QObject* object); + + QJsonArray _contents; + + QSet _sharedObjectIDs; + QJsonArray _sharedObjects; QSet _objectStreamerNames; QJsonArray _objectStreamers; - QSet _sharedObjectIDs; - QJsonArray _sharedObjects; + QSet _typeStreamerNames; + QJsonArray _typeStreamers; }; /// Tracks state when reading from JSON. @@ -958,6 +985,7 @@ public: virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; + virtual QJsonValue getJSONVariantData(JSONWriter& writer, const QVariant& value) const; virtual bool equal(const QVariant& first, const QVariant& second) const; @@ -1037,6 +1065,7 @@ public: virtual const char* getName() const; virtual void writeMetadata(Bitstream& out, bool full) const; virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; + virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; virtual Category getCategory() const; virtual int getBits() const; virtual QMetaEnum getMetaEnum() const; @@ -1099,6 +1128,7 @@ public: virtual void writeMetadata(Bitstream& out, bool full) const; virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; + virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; virtual void write(Bitstream& out, const QVariant& value) const; virtual QVariant read(Bitstream& in) const; virtual Category getCategory() const; @@ -1148,6 +1178,7 @@ public: virtual void writeMetadata(Bitstream& out, bool full) const; virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; + virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; virtual void write(Bitstream& out, const QVariant& value) const; virtual QVariant read(Bitstream& in) const; virtual Category getCategory() const; @@ -1219,6 +1250,7 @@ public: virtual void writeMetadata(Bitstream& out, bool full) const; virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; + virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; virtual void write(Bitstream& out, const QVariant& value) const; virtual QVariant read(Bitstream& in) const; virtual Category getCategory() const; @@ -1302,6 +1334,7 @@ public: virtual void writeMetadata(Bitstream& out, bool full) const; virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; + virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; virtual void write(Bitstream& out, const QVariant& value) const; virtual QVariant read(Bitstream& in) const; virtual Category getCategory() const; @@ -1316,6 +1349,7 @@ private: class GenericValueStreamer : public SimpleTypeStreamer { public: + QJsonValue getJSONVariantData(JSONWriter& writer, const QVariant& value) const; virtual void writeVariant(Bitstream& out, const QVariant& value) const; }; diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 6bd99a6c82..618178383f 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -243,6 +243,18 @@ static bool testSerialization(Bitstream::MetadataType metadataType) { return true; } + if (metadataType != Bitstream::FULL_METADATA) { + return false; + } + + // now write to JSON + JSONWriter jsonWriter; + jsonWriter << testObjectReadA; + jsonWriter << testObjectReadB; + jsonWriter << messageRead; + qDebug() << jsonWriter.getDocument().toJson(); + qDebug(); + return false; }