More commentation.

This commit is contained in:
Andrzej Kapolka 2014-06-17 19:15:29 -07:00
parent 5e0cab59ea
commit b8e6660e19
2 changed files with 47 additions and 6 deletions

View file

@ -1879,6 +1879,7 @@ QJsonDocument JSONWriter::getDocument() const {
}
JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode genericsMode) {
// create and map the type streamers in order
QJsonObject top = document.object();
foreach (const QJsonValue& element, top.value("types").toArray()) {
QJsonObject type = element.toObject();
@ -1889,10 +1890,11 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
baseStreamer = Bitstream::getEnumStreamersByName().value(latinName);
}
if (!baseStreamer && genericsMode == Bitstream::NO_GENERICS) {
continue;
continue; // no built-in type and no generics allowed; we give up
}
QString category = type.value("category").toString();
if (!baseStreamer || genericsMode == Bitstream::ALL_GENERICS) {
// create a generic streamer
TypeStreamerPointer streamer;
if (category == "ENUM") {
QVector<NameIntPair> values;
@ -1933,6 +1935,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
static_cast<GenericTypeStreamer*>(streamer.data())->_weakSelf = streamer;
continue;
}
// create a mapped streamer, determining along the way whether it matches our base
if (category == "ENUM") {
QHash<int, int> mappings;
int highestValue = 0;
@ -1949,6 +1952,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
}
matches &= (value == mapping);
}
// if everything matches our built-in enum, we can use that, which will be faster
if (matches) {
_typeStreamers.insert(name, baseStreamer->getSelf());
} else {
@ -1967,6 +1971,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
fields.append(StreamerIndexPair(streamer, index));
matches &= (index == i && streamer == metaFields.at(i).getStreamer());
}
// if everything matches our built-in streamable, we can use that, which will be faster
if (matches) {
_typeStreamers.insert(name, baseStreamer->getSelf());
} else {
@ -2001,6 +2006,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
}
}
// create and map the object streamers in order
foreach (const QJsonValue& element, top.value("classes").toArray()) {
QJsonObject clazz = element.toObject();
QString name = clazz.value("name").toString();
@ -2008,9 +2014,10 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
const ObjectStreamer* baseStreamer = Bitstream::getObjectStreamers().value(
Bitstream::getMetaObjects().value(latinName));
if (!baseStreamer && genericsMode == Bitstream::NO_GENERICS) {
continue;
continue; // no built-in class and no generics allowed; we give up
}
if (!baseStreamer || genericsMode == Bitstream::ALL_GENERICS) {
// create a generic streamer
QVector<StreamerNamePair> properties;
foreach (const QJsonValue& property, clazz.value("properties").toArray()) {
QJsonObject object = property.toObject();
@ -2023,6 +2030,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
static_cast<GenericObjectStreamer*>(streamer.data())->_weakSelf = streamer;
continue;
}
// create a mapped streamer, determining along the way whether it matches our base
const QMetaObject* metaObject = baseStreamer->getMetaObject();
const QVector<StreamerPropertyPair>& baseProperties = baseStreamer->getProperties();
QVector<StreamerPropertyPair> properties;
@ -2039,6 +2047,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
matches &= (typeStreamer == baseProperty.first &&
metaProperty.propertyIndex() == baseProperty.second.propertyIndex());
}
// if everything matches our built-in type, we can use that directly, which will be faster
if (matches) {
_objectStreamers.insert(name, baseStreamer->getSelf());
} else {
@ -2046,6 +2055,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
}
}
// create and map the objects in order
foreach (const QJsonValue& element, top.value("objects").toArray()) {
QJsonObject object = element.toObject();
int id = object.value("id").toInt();
@ -2056,6 +2066,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge
}
}
// prepare the contents for extraction
_contents = top.value("contents").toArray();
_contentsIterator = _contents.constBegin();
}

View file

@ -205,6 +205,36 @@ template<class K, class P, class V> inline RepeatedValueStreamer<K, P, V>&
/// version-resilient persistence, the class provides a metadata system that maps stored types to local types (or to
/// generic containers), allowing one to add and remove fields to classes without breaking compatibility with previously
/// stored data.
///
/// The basic usage requires one to create a Bitstream that wraps an underlying QDataStream, specifying the metadata type
/// desired and (for readers) the generics mode. Then, one uses the << or >> operators to write or read values to/from
/// the stream (a stream instance may be used for reading or writing, but not both). For write streams, the flush
/// function should be called on completion to write any partial data.
///
/// Polymorphic types are supported via the QVariant and QObject*/SharedObjectPointer types. When you write a QVariant or
/// QObject, the type or class name (at minimum) is written to the stream. When you read a QVariant or QObject, the default
/// behavior is to look for a corresponding registered type with the written name. With hash metadata, Bitstream can verify
/// that the local type matches the stream type, throwing the streamed version away if not. With full metadata, Bitstream can
/// create a mapping from the streamed type to the local type that applies the intersection of the two types' fields.
///
/// To register types for streaming, select from the provided templates and macros. To register a QObject (or SharedObject)
/// subclass, use REGISTER_META_OBJECT in the class's source file. To register a streamable class for use in QVariant, use
/// the STREAMABLE/STREAM/DECLARE_STREAMABLE_METATYPE macros and use the mtc tool to generate the associated implementation
/// code. To register a QObject enum for use outside the QObject's direct properties, use the
/// DECLARE_ENUM_METATYPE/IMPLEMENT_ENUM_METATYPE macro pair. To register a collection type (QList, QVector, QSet, QMap) of
/// streamable types, use the registerCollectionMetaType template function.
///
/// Delta-streaming is supported through the writeDelta/readDelta functions (analogous to <</>>), which accept a reference
/// value and stream only the information necessary to turn the reference into the target value. This assumes that the
/// reference value provided when reading is identical to the one used when writing.
///
/// Special delta handling is provided for objects tracked by SharedObjectPointers. SharedObjects have IDs (representing their
/// unique identity on one system) as well as origin IDs (representing their identity as preserved over the course of
/// mutation). Once a shared object with a given ID is written (and its mapping persisted), that object's state will not be
/// written again; only its ID will be sent. However, if an object with a new ID but the same origin ID is written, that
/// object's state will be encoded as a delta between the previous object and the new one. So, to transmit delta-encoded
/// objects, one should treat each local SharedObject instance as immutable, replacing it when mutated with a cloned instance
/// generated by calling SharedObject::clone(true) and applying the desired changes.
class Bitstream : public QObject {
Q_OBJECT
@ -1001,7 +1031,7 @@ protected:
friend class Bitstream;
const QMetaObject* _metaObject;
ObjectStreamerPointer _self;
ObjectStreamerPointer _self; ///< set/used for built-in classes (never deleted), to obtain shared pointers
};
/// A streamer that maps to a local class.
@ -1050,7 +1080,7 @@ private:
friend class JSONReader;
QByteArray _name;
WeakObjectStreamerPointer _weakSelf;
WeakObjectStreamerPointer _weakSelf; ///< promoted to strong references in GenericSharedObject when reading
QVector<StreamerNamePair> _properties;
QByteArray _hash;
};
@ -1184,7 +1214,7 @@ protected:
friend class Bitstream;
int _type;
TypeStreamerPointer _self;
TypeStreamerPointer _self; ///< set/used for built-in types (never deleted), to obtain shared pointers
};
QDebug& operator<<(QDebug& debug, const TypeStreamer* typeStreamer);
@ -1278,7 +1308,7 @@ protected:
friend class JSONReader;
QByteArray _name;
WeakTypeStreamerPointer _weakSelf;
WeakTypeStreamerPointer _weakSelf; ///< promoted to strong references in GenericValue when reading
};
/// A streamer for generic enums.