diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index aa5ed3fa5e..b88f536d1a 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -1657,107 +1657,172 @@ const TypeStreamer* Bitstream::createInvalidTypeStreamer() { return streamer; } -JSONWriter& JSONWriter::operator<<(bool value) { - _contents.append(value); - return *this; +QJsonValue JSONWriter::getData(bool value) { + return value; } -JSONWriter& JSONWriter::operator<<(int value) { - _contents.append(value); - return *this; +QJsonValue JSONWriter::getData(int value) { + return value; } -JSONWriter& JSONWriter::operator<<(uint value) { - _contents.append((int)value); - return *this; +QJsonValue JSONWriter::getData(uint value) { + return (int)value; } -JSONWriter& JSONWriter::operator<<(float value) { - _contents.append((double)value); - return *this; +QJsonValue JSONWriter::getData(float value) { + return (double)value; } -JSONWriter& JSONWriter::operator<<(const QByteArray& value) { - _contents.append(QString(value.toPercentEncoding())); - return *this; +QJsonValue JSONWriter::getData(const QByteArray& value) { + return QString(value.toPercentEncoding()); } -JSONWriter& JSONWriter::operator<<(const QColor& value) { - _contents.append(value.name()); - return *this; +QJsonValue JSONWriter::getData(const QColor& value) { + return value.name(); } -JSONWriter& JSONWriter::operator<<(const QScriptValue& value) { - return *this; +QJsonValue JSONWriter::getData(const QScriptValue& value) { + QJsonObject object; + if (value.isUndefined()) { + object.insert("type", QString("UNDEFINED")); + + } else if (value.isNull()) { + object.insert("type", QString("NULL")); + + } else if (value.isBool()) { + object.insert("type", QString("BOOL")); + object.insert("value", value.toBool()); + + } else if (value.isNumber()) { + object.insert("type", QString("NUMBER")); + object.insert("value", value.toNumber()); + + } else if (value.isString()) { + object.insert("type", QString("STRING")); + object.insert("value", value.toString()); + + } else if (value.isVariant()) { + object.insert("type", QString("VARIANT")); + object.insert("value", getData(value.toVariant())); + + } else if (value.isQObject()) { + object.insert("type", QString("QOBJECT")); + object.insert("value", getData(value.toQObject())); + + } else if (value.isQMetaObject()) { + object.insert("type", QString("QMETAOBJECT")); + object.insert("value", getData(value.toQMetaObject())); + + } else if (value.isDate()) { + object.insert("type", QString("DATE")); + object.insert("value", getData(value.toDateTime())); + + } else if (value.isRegExp()) { + object.insert("type", QString("REGEXP")); + object.insert("value", getData(value.toRegExp())); + + } else if (value.isArray()) { + object.insert("type", QString("ARRAY")); + QJsonArray array; + int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32(); + for (int i = 0; i < length; i++) { + array.append(getData(value.property(i))); + } + object.insert("value", array); + + } else if (value.isObject()) { + object.insert("type", QString("OBJECT")); + QJsonObject valueObject; + for (QScriptValueIterator it(value); it.hasNext(); ) { + it.next(); + valueObject.insert(it.name(), getData(it.value())); + } + object.insert("value", valueObject); + + } else { + object.insert("type", QString("INVALID")); + } + return object; } -JSONWriter& JSONWriter::operator<<(const QString& value) { - _contents.append(value); - return *this; +QJsonValue JSONWriter::getData(const QString& value) { + return value; } -JSONWriter& JSONWriter::operator<<(const QUrl& value) { - _contents.append(value.toString()); - return *this; +QJsonValue JSONWriter::getData(const QUrl& value) { + return value.toString(); } -JSONWriter& JSONWriter::operator<<(const glm::vec3& value) { +QJsonValue JSONWriter::getData(const QDateTime& value) { + return (qsreal)value.toMSecsSinceEpoch(); +} + +QJsonValue JSONWriter::getData(const QRegExp& value) { + QJsonObject object; + object.insert("pattern", value.pattern()); + object.insert("caseSensitivity", (int)value.caseSensitivity()); + object.insert("patternSyntax", (int)value.patternSyntax()); + object.insert("minimal", value.isMinimal()); + return object; +} + +QJsonValue JSONWriter::getData(const glm::vec3& value) { QJsonArray array; array.append(value.x); array.append(value.y); array.append(value.z); - _contents.append(array); - return *this; + return array; } -JSONWriter& JSONWriter::operator<<(const glm::quat& value) { +QJsonValue JSONWriter::getData(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; + return array; } -JSONWriter& JSONWriter::operator<<(const QMetaObject* metaObject) { +QJsonValue JSONWriter::getData(const QMetaObject* metaObject) { if (!metaObject) { - _contents.append(QJsonValue()); - return *this; + return QJsonValue(); } const ObjectStreamer* streamer = Bitstream::getObjectStreamers().value(metaObject); addObjectStreamer(streamer); - _contents.append(QString(streamer->getName())); - return *this; + return QString(streamer->getName()); } -JSONWriter& JSONWriter::operator<<(const QVariant& value) { +QJsonValue JSONWriter::getData(const QVariant& value) { if (!value.isValid()) { - _contents.append(QJsonValue()); - return *this; + return QJsonValue(); } const TypeStreamer* streamer = Bitstream::getTypeStreamers().value(value.userType()); if (streamer) { - _contents.append(streamer->getJSONVariantData(*this, value)); + return streamer->getJSONVariantData(*this, value); } else { qWarning() << "Non-streamable type:" << value.typeName(); + return QJsonValue(); } - return *this; } -JSONWriter& JSONWriter::operator<<(const SharedObjectPointer& object) { +QJsonValue JSONWriter::getData(const SharedObjectPointer& object) { if (object) { addSharedObject(object); - _contents.append(object->getID()); + return object->getID(); } else { - _contents.append(0); + return 0; } - return *this; } -JSONWriter& JSONWriter::operator<<(const QObject* object) { - _contents.append(getData(object)); - return *this; +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); } void JSONWriter::addTypeStreamer(const TypeStreamer* streamer) { @@ -1798,7 +1863,7 @@ void JSONWriter::addSharedObject(const SharedObjectPointer& object) { QJsonObject sharedObject; sharedObject.insert("id", object->getID()); sharedObject.insert("originID", object->getOriginID()); - sharedObject.insert("data", getData(object.data())); + sharedObject.insert("data", getData(static_cast(object.data()))); _sharedObjects.replace(index, sharedObject); } } @@ -1812,17 +1877,6 @@ QJsonDocument JSONWriter::getDocument() const { 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) { } diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 159633c810..23943444d9 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -776,22 +776,32 @@ template inline Bitstream& Bitstream::operator>>(QHash& class JSONWriter { public: - 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); + QJsonValue getData(bool value); + QJsonValue getData(int value); + QJsonValue getData(uint value); + QJsonValue getData(float value); + QJsonValue getData(const QByteArray& value); + QJsonValue getData(const QColor& value); + QJsonValue getData(const QScriptValue& value); + QJsonValue getData(const QString& value); + QJsonValue getData(const QUrl& value); + QJsonValue getData(const QDateTime& value); + QJsonValue getData(const QRegExp& value); + QJsonValue getData(const glm::vec3& value); + QJsonValue getData(const glm::quat& value); + QJsonValue getData(const QMetaObject* value); + QJsonValue getData(const QVariant& value); + QJsonValue getData(const SharedObjectPointer& value); + QJsonValue getData(const QObject* value); - JSONWriter& operator<<(const QVariant& value); - JSONWriter& operator<<(const SharedObjectPointer& object); - JSONWriter& operator<<(const QObject* object); + template QJsonValue getData(const T& value); + + template QJsonValue getData(const QList& list); + template QJsonValue getData(const QVector& list); + template QJsonValue getData(const QSet& set); + template QJsonValue getData(const QHash& hash); + + template JSONWriter& operator<<(const T& value) { _contents.append(getData(value)); return *this; } void addSharedObject(const SharedObjectPointer& object); void addObjectStreamer(const ObjectStreamer* streamer); @@ -801,8 +811,6 @@ public: private: - QJsonValue getData(const QObject* object); - QJsonArray _contents; QSet _sharedObjectIDs; @@ -815,6 +823,45 @@ private: QJsonArray _typeStreamers; }; +template inline QJsonValue JSONWriter::getData(const T& value) { + return QJsonValue(); +} + +template inline QJsonValue JSONWriter::getData(const QList& list) { + QJsonArray array; + foreach (const T& value, list) { + array.append(getData(value)); + } + return array; +} + +template inline QJsonValue JSONWriter::getData(const QVector& vector) { + QJsonArray array; + foreach (const T& value, vector) { + array.append(getData(value)); + } + return array; +} + +template inline QJsonValue JSONWriter::getData(const QSet& set) { + QJsonArray array; + foreach (const T& value, set) { + array.append(getData(value)); + } + return array; +} + +template inline QJsonValue JSONWriter::getData(const QHash& hash) { + QJsonArray array; + for (typename QHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); it++) { + QJsonArray pair; + pair.append(getData(it.key())); + pair.append(getData(it.value())); + array.append(pair); + } + return array; +} + /// Tracks state when reading from JSON. class JSONReader { public: @@ -1042,6 +1089,8 @@ QDebug& operator<<(QDebug& debug, const QMetaObject* metaObject); template class SimpleTypeStreamer : public TypeStreamer { public: + virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const { + return writer.getData(value.value()); } virtual bool equal(const QVariant& first, const QVariant& second) const { return first.value() == second.value(); } virtual void write(Bitstream& out, const QVariant& value) const { out << value.value(); } virtual QVariant read(Bitstream& in) const { T value; in >> value; return QVariant::fromValue(value); }