Working on JSON encoding.

This commit is contained in:
Andrzej Kapolka 2014-06-13 16:25:38 -07:00
parent 10875c5e61
commit 7db05f2c8e
2 changed files with 276 additions and 1 deletions

View file

@ -1657,6 +1657,49 @@ const TypeStreamer* Bitstream::createInvalidTypeStreamer() {
return streamer;
}
void JSONWriter::addTypeStreamer(const TypeStreamer* streamer) {
if (!_typeStreamerNames.contains(streamer->getName())) {
_typeStreamerNames.insert(streamer->getName());
// start with a placeholder; then remove/replace with actual metadata
int index = _typeStreamers.size();
_typeStreamers.append(QJsonValue());
QJsonValue metadata = streamer->getJSONMetadata(*this);
if (metadata.isNull()) {
_typeStreamers.removeAt(index);
} else {
_typeStreamers.replace(index, metadata);
}
}
}
void JSONWriter::addObjectStreamer(const ObjectStreamer* streamer) {
if (!_objectStreamerNames.contains(streamer->getName())) {
_objectStreamerNames.insert(streamer->getName());
// start with a placeholder; then replace with actual metadata
int index = _objectStreamers.size();
_objectStreamers.append(QJsonValue());
_objectStreamers.replace(index, streamer->getJSONMetadata(*this));
}
}
void JSONWriter::addSharedObject(const SharedObjectPointer& object) {
if (!_sharedObjectIDs.contains(object->getID())) {
_sharedObjectIDs.insert(object->getID());
// start with a placeholder; then replace with actual object
int index = _sharedObjects.size();
_sharedObjects.append(QJsonValue());
QJsonObject sharedObject;
sharedObject.insert("id", object->getID());
sharedObject.insert("originID", object->getOriginID());
_sharedObjects.replace(index, sharedObject);
}
}
ObjectStreamer::ObjectStreamer(const QMetaObject* metaObject) :
_metaObject(metaObject) {
}
@ -1699,6 +1742,33 @@ void MappedObjectStreamer::writeMetadata(Bitstream& out, bool full) const {
}
}
QJsonObject MappedObjectStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(_metaObject->className()));
QJsonArray properties;
foreach (const StreamerPropertyPair& property, _properties) {
QJsonObject object;
writer.addTypeStreamer(property.first.data());
object.insert("type", QString(property.first->getName()));
object.insert("name", QString(property.second.name()));
properties.append(object);
}
metadata.insert("properties", properties);
return metadata;
}
QJsonObject MappedObjectStreamer::getJSONData(JSONWriter& writer, const QObject* object) const {
QJsonObject data;
writer.addObjectStreamer(this);
data.insert("class", QString(_metaObject->className()));
QJsonArray properties;
foreach (const StreamerPropertyPair& property, _properties) {
properties.append(property.first->getJSONData(writer, property.second.read(object)));
}
data.insert("properties", properties);
return data;
}
void MappedObjectStreamer::write(Bitstream& out, const QObject* object) const {
foreach (const StreamerPropertyPair& property, _properties) {
property.first->write(out, property.second.read(object));
@ -1775,6 +1845,34 @@ void GenericObjectStreamer::writeMetadata(Bitstream& out, bool full) const {
}
}
QJsonObject GenericObjectStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(_name));
QJsonArray properties;
foreach (const StreamerNamePair& property, _properties) {
QJsonObject object;
writer.addTypeStreamer(property.first.data());
object.insert("type", QString(property.first->getName()));
object.insert("name", QString(property.second));
properties.append(object);
}
metadata.insert("properties", properties);
return metadata;
}
QJsonObject GenericObjectStreamer::getJSONData(JSONWriter& writer, const QObject* object) const {
QJsonObject data;
writer.addObjectStreamer(this);
data.insert("class", QString(_name));
QJsonArray properties;
const QVariantList& values = static_cast<const GenericSharedObject*>(object)->getValues();
for (int i = 0; i < _properties.size(); i++) {
properties.append(_properties.at(i).first->getJSONData(writer, values.at(i)));
}
data.insert("properties", properties);
return data;
}
void GenericObjectStreamer::write(Bitstream& out, const QObject* object) const {
const QVariantList& values = static_cast<const GenericSharedObject*>(object)->getValues();
for (int i = 0; i < _properties.size(); i++) {
@ -1876,6 +1974,55 @@ void TypeStreamer::writeMetadata(Bitstream& out, bool full) const {
}
}
QJsonValue TypeStreamer::getJSONMetadata(JSONWriter& writer) const {
Category category = getCategory();
switch (category) {
case STREAMABLE_CATEGORY: {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("STREAMABLE"));
QJsonArray fields;
foreach (const MetaField& metaField, getMetaFields()) {
QJsonObject field;
writer.addTypeStreamer(metaField.getStreamer());
field.insert("type", QString(metaField.getStreamer()->getName()));
field.insert("name", QString(metaField.getName()));
fields.append(field);
}
metadata.insert("fields", fields);
return metadata;
}
case LIST_CATEGORY:
case SET_CATEGORY: {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString(category == LIST_CATEGORY ? "LIST" : "SET"));
const TypeStreamer* valueStreamer = getValueStreamer();
writer.addTypeStreamer(valueStreamer);
metadata.insert("valueType", QString(valueStreamer->getName()));
return metadata;
}
case MAP_CATEGORY: {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("MAP"));
const TypeStreamer* keyStreamer = getKeyStreamer();
writer.addTypeStreamer(keyStreamer);
metadata.insert("keyType", QString(keyStreamer->getName()));
const TypeStreamer* valueStreamer = getValueStreamer();
writer.addTypeStreamer(valueStreamer);
metadata.insert("valueType", QString(valueStreamer->getName()));
return metadata;
}
default:
return QJsonValue();
}
}
QJsonValue TypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const {
return QJsonValue();
}
bool TypeStreamer::equal(const QVariant& first, const QVariant& second) const {
return first == second;
}
@ -2045,6 +2192,22 @@ void EnumTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
}
}
QJsonValue EnumTypeStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("ENUM"));
QJsonArray values;
QMetaEnum metaEnum = getMetaEnum();
for (int i = 0; i < metaEnum.keyCount(); i++) {
QJsonObject value;
value.insert("key", QString(metaEnum.key(i)));
value.insert("value", metaEnum.value(i));
values.append(value);
}
metadata.insert("values", values);
return metadata;
}
TypeStreamer::Category EnumTypeStreamer::getCategory() const {
return ENUM_CATEGORY;
}
@ -2194,6 +2357,21 @@ void GenericEnumTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
}
}
QJsonValue GenericEnumTypeStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("ENUM"));
QJsonArray values;
foreach (const NameIntPair& value, _values) {
QJsonObject object;
object.insert("key", QString(value.first));
object.insert("value", value.second);
values.append(object);
}
metadata.insert("values", values);
return metadata;
}
void GenericEnumTypeStreamer::write(Bitstream& out, const QVariant& value) const {
int intValue = value.toInt();
out.write(&intValue, _bits);
@ -2270,6 +2448,22 @@ void GenericStreamableTypeStreamer::writeMetadata(Bitstream& out, bool full) con
}
}
QJsonValue GenericStreamableTypeStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("STREAMABLE"));
QJsonArray fields;
foreach (const StreamerNamePair& field, _fields) {
QJsonObject object;
writer.addTypeStreamer(field.first.data());
object.insert("type", QString(field.first->getName()));
object.insert("name", QString(field.second));
fields.append(object);
}
metadata.insert("fields", fields);
return metadata;
}
void GenericStreamableTypeStreamer::write(Bitstream& out, const QVariant& value) const {
QVariantList values = value.toList();
for (int i = 0; i < _fields.size(); i++) {
@ -2334,6 +2528,15 @@ void GenericListTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
out << _valueStreamer.data();
}
QJsonValue GenericListTypeStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("LIST"));
writer.addTypeStreamer(_valueStreamer.data());
metadata.insert("valueType", QString(_valueStreamer->getName()));
return metadata;
}
void GenericListTypeStreamer::write(Bitstream& out, const QVariant& value) const {
QVariantList values = value.toList();
out << values.size();
@ -2376,6 +2579,15 @@ GenericSetTypeStreamer::GenericSetTypeStreamer(const QByteArray& name, const Typ
GenericListTypeStreamer(name, valueStreamer) {
}
QJsonValue GenericSetTypeStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("SET"));
writer.addTypeStreamer(_valueStreamer.data());
metadata.insert("valueType", QString(_valueStreamer->getName()));
return metadata;
}
TypeStreamer::Category GenericSetTypeStreamer::getCategory() const {
return SET_CATEGORY;
}
@ -2437,6 +2649,17 @@ void GenericMapTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
out << _keyStreamer.data() << _valueStreamer.data();
}
QJsonValue GenericMapTypeStreamer::getJSONMetadata(JSONWriter& writer) const {
QJsonObject metadata;
metadata.insert("name", QString(getName()));
metadata.insert("category", QString("MAP"));
writer.addTypeStreamer(_keyStreamer.data());
metadata.insert("keyType", QString(_keyStreamer->getName()));
writer.addTypeStreamer(_valueStreamer.data());
metadata.insert("valueType", QString(_valueStreamer->getName()));
return metadata;
}
void GenericMapTypeStreamer::write(Bitstream& out, const QVariant& value) const {
QVariantPairList values = value.value<QVariantPairList>();
out << values.size();

View file

@ -13,6 +13,8 @@
#define hifi_Bitstream_h
#include <QHash>
#include <QJsonArray>
#include <QJsonObject>
#include <QMetaProperty>
#include <QMetaType>
#include <QPointer>
@ -766,6 +768,41 @@ template<class K, class V> inline Bitstream& Bitstream::operator>>(QHash<K, V>&
return *this;
}
/// Tracks state when writing to JSON.
class JSONWriter {
public:
void addTypeStreamer(const TypeStreamer* streamer);
void addObjectStreamer(const ObjectStreamer* streamer);
void addSharedObject(const SharedObjectPointer& object);
private:
QSet<QByteArray> _typeStreamerNames;
QJsonArray _typeStreamers;
QSet<QByteArray> _objectStreamerNames;
QJsonArray _objectStreamers;
QSet<int> _sharedObjectIDs;
QJsonArray _sharedObjects;
};
/// Tracks state when reading from JSON.
class JSONReader {
public:
TypeStreamerPointer getTypeStreamer(const QByteArray& name) const { return _typeStreamers.value(name); }
ObjectStreamerPointer getObjectStreamer(const QByteArray& name) const { return _objectStreamers.value(name); }
SharedObjectPointer getSharedObject(int id) const { return _sharedObjects.value(id); }
private:
QHash<QByteArray, TypeStreamerPointer> _typeStreamers;
QHash<QByteArray, ObjectStreamerPointer> _objectStreamers;
QHash<int, SharedObjectPointer> _sharedObjects;
};
typedef QPair<TypeStreamerPointer, QMetaProperty> StreamerPropertyPair;
/// Contains the information required to stream an object.
@ -780,6 +817,8 @@ public:
virtual const char* getName() const = 0;
virtual const QVector<StreamerPropertyPair>& getProperties() const;
virtual void writeMetadata(Bitstream& out, bool full) const = 0;
virtual QJsonObject getJSONMetadata(JSONWriter& writer) const = 0;
virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const = 0;
virtual void write(Bitstream& out, const QObject* object) const = 0;
virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const = 0;
virtual QObject* read(Bitstream& in, QObject* object = NULL) const = 0;
@ -802,6 +841,8 @@ public:
virtual const char* getName() const;
virtual const QVector<StreamerPropertyPair>& getProperties() const;
virtual void writeMetadata(Bitstream& out, bool full) const;
virtual QJsonObject getJSONMetadata(JSONWriter& writer) const;
virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const;
virtual void write(Bitstream& out, const QObject* object) const;
virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const;
virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
@ -822,6 +863,8 @@ public:
virtual const char* getName() const;
virtual void writeMetadata(Bitstream& out, bool full) const;
virtual QJsonObject getJSONMetadata(JSONWriter& writer) const;
virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const;
virtual void write(Bitstream& out, const QObject* object) const;
virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const;
virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
@ -913,6 +956,9 @@ 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 bool equal(const QVariant& first, const QVariant& second) const;
virtual void write(Bitstream& out, const QVariant& value) const;
@ -990,6 +1036,7 @@ public:
virtual const char* getName() const;
virtual void writeMetadata(Bitstream& out, bool full) const;
virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
virtual Category getCategory() const;
virtual int getBits() const;
virtual QMetaEnum getMetaEnum() const;
@ -1051,6 +1098,7 @@ public:
GenericEnumTypeStreamer(const QByteArray& name, const QVector<NameIntPair>& values, int bits, const QByteArray& hash);
virtual void writeMetadata(Bitstream& out, bool full) const;
virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
virtual void write(Bitstream& out, const QVariant& value) const;
virtual QVariant read(Bitstream& in) const;
virtual Category getCategory() const;
@ -1099,6 +1147,7 @@ public:
GenericStreamableTypeStreamer(const QByteArray& name, const QVector<StreamerNamePair>& fields, const QByteArray& hash);
virtual void writeMetadata(Bitstream& out, bool full) const;
virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
virtual void write(Bitstream& out, const QVariant& value) const;
virtual QVariant read(Bitstream& in) const;
virtual Category getCategory() const;
@ -1169,11 +1218,12 @@ public:
GenericListTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer);
virtual void writeMetadata(Bitstream& out, bool full) const;
virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
virtual void write(Bitstream& out, const QVariant& value) const;
virtual QVariant read(Bitstream& in) const;
virtual Category getCategory() const;
private:
protected:
TypeStreamerPointer _valueStreamer;
};
@ -1206,6 +1256,7 @@ public:
GenericSetTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer);
virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
virtual Category getCategory() const;
};
@ -1250,6 +1301,7 @@ public:
const TypeStreamerPointer& valueStreamer);
virtual void writeMetadata(Bitstream& out, bool full) const;
virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
virtual void write(Bitstream& out, const QVariant& value) const;
virtual QVariant read(Bitstream& in) const;
virtual Category getCategory() const;