mirror of
https://github.com/overte-org/overte.git
synced 2025-08-16 11:51:31 +02:00
More progress on generics.
This commit is contained in:
parent
6260d661f3
commit
6c98248e50
2 changed files with 164 additions and 41 deletions
|
@ -1216,7 +1216,15 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
|||
}
|
||||
return *this;
|
||||
}
|
||||
if (_genericsMode == ALL_GENERICS) {
|
||||
streamer = readGenericTypeStreamer(typeName, category);
|
||||
return *this;
|
||||
}
|
||||
if (!baseStreamer) {
|
||||
if (_genericsMode == FALLBACK_GENERICS) {
|
||||
streamer = readGenericTypeStreamer(typeName, category);
|
||||
return *this;
|
||||
}
|
||||
baseStreamer = getInvalidTypeStreamer();
|
||||
}
|
||||
switch (category) {
|
||||
|
@ -1224,8 +1232,7 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
|||
if (_metadataType == FULL_METADATA) {
|
||||
int keyCount;
|
||||
*this >> keyCount;
|
||||
QMetaEnum metaEnum = (baseStreamer && baseStreamer->getCategory() == TypeStreamer::ENUM_CATEGORY) ?
|
||||
baseStreamer->getMetaEnum() : QMetaEnum();
|
||||
QMetaEnum metaEnum = baseStreamer->getMetaEnum();
|
||||
QHash<int, int> mappings;
|
||||
bool matches = (keyCount == metaEnum.keyCount());
|
||||
int highestValue = 0;
|
||||
|
@ -1248,7 +1255,7 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
|||
int bits;
|
||||
*this >> bits;
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
if (baseStreamer && baseStreamer->getCategory() == TypeStreamer::ENUM_CATEGORY) {
|
||||
if (baseStreamer->getCategory() == TypeStreamer::ENUM_CATEGORY) {
|
||||
QMetaEnum metaEnum = baseStreamer->getMetaEnum();
|
||||
for (int i = 0; i < metaEnum.keyCount(); i++) {
|
||||
hash.addData(metaEnum.key(i), strlen(metaEnum.key(i)) + 1);
|
||||
|
@ -1269,8 +1276,7 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
|||
case TypeStreamer::SET_CATEGORY: {
|
||||
TypeStreamerPointer valueStreamer;
|
||||
*this >> valueStreamer;
|
||||
if (!(baseStreamer && baseStreamer->getCategory() == category &&
|
||||
valueStreamer == baseStreamer->getValueStreamer())) {
|
||||
if (!(baseStreamer->getCategory() == category && valueStreamer == baseStreamer->getValueStreamer())) {
|
||||
streamer = TypeStreamerPointer(category == TypeStreamer::LIST_CATEGORY ?
|
||||
new MappedListTypeStreamer(baseStreamer, valueStreamer) :
|
||||
new MappedSetTypeStreamer(baseStreamer, valueStreamer));
|
||||
|
@ -1280,7 +1286,7 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
|||
case TypeStreamer::MAP_CATEGORY: {
|
||||
TypeStreamerPointer keyStreamer, valueStreamer;
|
||||
*this >> keyStreamer >> valueStreamer;
|
||||
if (!(baseStreamer && baseStreamer->getCategory() == TypeStreamer::MAP_CATEGORY &&
|
||||
if (!(baseStreamer->getCategory() == TypeStreamer::MAP_CATEGORY &&
|
||||
keyStreamer == baseStreamer->getKeyStreamer() && valueStreamer == baseStreamer->getValueStreamer())) {
|
||||
streamer = TypeStreamerPointer(new MappedMapTypeStreamer(baseStreamer, keyStreamer, valueStreamer));
|
||||
}
|
||||
|
@ -1298,9 +1304,7 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
|||
if (_metadataType == FULL_METADATA) {
|
||||
QByteArray fieldName;
|
||||
*this >> fieldName;
|
||||
if (baseStreamer) {
|
||||
index = baseStreamer->getFieldIndex(fieldName);
|
||||
}
|
||||
index = baseStreamer->getFieldIndex(fieldName);
|
||||
}
|
||||
fields[i] = StreamerIndexPair(typeStreamer, index);
|
||||
}
|
||||
|
@ -1308,49 +1312,44 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
|||
if (_metadataType == HASH_METADATA) {
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
bool matches = true;
|
||||
if (baseStreamer) {
|
||||
const QVector<MetaField>& localFields = baseStreamer->getMetaFields();
|
||||
if (fieldCount != localFields.size()) {
|
||||
matches = false;
|
||||
|
||||
} else {
|
||||
if (fieldCount == 0) {
|
||||
return *this;
|
||||
}
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
const MetaField& localField = localFields.at(i);
|
||||
if (fields.at(i).first != localField.getStreamer()) {
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
hash.addData(localField.getName().constData(), localField.getName().size() + 1);
|
||||
}
|
||||
const QVector<MetaField>& localFields = baseStreamer->getMetaFields();
|
||||
if (fieldCount != localFields.size()) {
|
||||
matches = false;
|
||||
|
||||
} else {
|
||||
if (fieldCount == 0) {
|
||||
return *this;
|
||||
}
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
const MetaField& localField = localFields.at(i);
|
||||
if (fields.at(i).first != localField.getStreamer()) {
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
hash.addData(localField.getName().constData(), localField.getName().size() + 1);
|
||||
}
|
||||
}
|
||||
QByteArray localHashResult = hash.result();
|
||||
QByteArray remoteHashResult(localHashResult.size(), 0);
|
||||
read(remoteHashResult.data(), remoteHashResult.size() * BITS_IN_BYTE);
|
||||
if (baseStreamer && matches && localHashResult == remoteHashResult) {
|
||||
if (matches && localHashResult == remoteHashResult) {
|
||||
// since everything is the same, we can use the default streamer
|
||||
return *this;
|
||||
}
|
||||
} else if (baseStreamer) {
|
||||
// if all fields are the same type and in the right order, we can use the (more efficient) default streamer
|
||||
const QVector<MetaField>& localFields = baseStreamer->getMetaFields();
|
||||
if (fieldCount != localFields.size()) {
|
||||
}
|
||||
// if all fields are the same type and in the right order, we can use the (more efficient) default streamer
|
||||
const QVector<MetaField>& localFields = baseStreamer->getMetaFields();
|
||||
if (fieldCount != localFields.size()) {
|
||||
streamer = TypeStreamerPointer(new MappedStreamableTypeStreamer(baseStreamer, fields));
|
||||
return *this;
|
||||
}
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
const StreamerIndexPair& field = fields.at(i);
|
||||
if (field.first != localFields.at(i).getStreamer() || field.second != i) {
|
||||
streamer = TypeStreamerPointer(new MappedStreamableTypeStreamer(baseStreamer, fields));
|
||||
return *this;
|
||||
}
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
const StreamerIndexPair& field = fields.at(i);
|
||||
if (field.first != localFields.at(i).getStreamer() || field.second != i) {
|
||||
streamer = TypeStreamerPointer(new MappedStreamableTypeStreamer(baseStreamer, fields));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
streamer = TypeStreamerPointer(new MappedStreamableTypeStreamer(baseStreamer, fields));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1444,6 +1443,81 @@ void Bitstream::clearSharedObject(QObject* object) {
|
|||
}
|
||||
}
|
||||
|
||||
const int MD5_HASH_SIZE = 16;
|
||||
|
||||
TypeStreamerPointer Bitstream::readGenericTypeStreamer(const QByteArray& name, int category) {
|
||||
TypeStreamerPointer streamer;
|
||||
switch (category) {
|
||||
case TypeStreamer::ENUM_CATEGORY: {
|
||||
QVector<NameIntPair> values;
|
||||
int bits;
|
||||
QByteArray hash;
|
||||
if (_metadataType == FULL_METADATA) {
|
||||
int keyCount;
|
||||
*this >> keyCount;
|
||||
values.resize(keyCount);
|
||||
int highestValue = 0;
|
||||
for (int i = 0; i < keyCount; i++) {
|
||||
QByteArray name;
|
||||
int value;
|
||||
*this >> name >> value;
|
||||
values[i] = NameIntPair(name, value);
|
||||
highestValue = qMax(highestValue, value);
|
||||
}
|
||||
bits = getBitsForHighestValue(highestValue);
|
||||
|
||||
} else {
|
||||
*this >> bits;
|
||||
hash.resize(MD5_HASH_SIZE);
|
||||
read(hash.data(), hash.size() * BITS_IN_BYTE);
|
||||
}
|
||||
streamer = TypeStreamerPointer(new GenericEnumTypeStreamer(name, values, bits, hash));
|
||||
break;
|
||||
}
|
||||
case TypeStreamer::STREAMABLE_CATEGORY: {
|
||||
int fieldCount;
|
||||
*this >> fieldCount;
|
||||
QVector<StreamerNamePair> fields(fieldCount);
|
||||
QByteArray hash;
|
||||
if (fieldCount == 0) {
|
||||
streamer = TypeStreamerPointer(new GenericStreamableTypeStreamer(name, fields, hash));
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
TypeStreamerPointer streamer;
|
||||
*this >> streamer;
|
||||
QByteArray name;
|
||||
if (_metadataType == FULL_METADATA) {
|
||||
*this >> name;
|
||||
}
|
||||
fields[i] = StreamerNamePair(streamer, name);
|
||||
}
|
||||
if (_metadataType == HASH_METADATA) {
|
||||
hash.resize(MD5_HASH_SIZE);
|
||||
read(hash.data(), hash.size() * BITS_IN_BYTE);
|
||||
}
|
||||
streamer = TypeStreamerPointer(new GenericStreamableTypeStreamer(name, fields, hash));
|
||||
break;
|
||||
}
|
||||
case TypeStreamer::LIST_CATEGORY:
|
||||
case TypeStreamer::SET_CATEGORY: {
|
||||
TypeStreamerPointer valueStreamer;
|
||||
*this >> valueStreamer;
|
||||
streamer = TypeStreamerPointer(category == TypeStreamer::LIST_CATEGORY ?
|
||||
new GenericListTypeStreamer(name, valueStreamer) : new GenericSetTypeStreamer(name, valueStreamer));
|
||||
break;
|
||||
}
|
||||
case TypeStreamer::MAP_CATEGORY: {
|
||||
TypeStreamerPointer keyStreamer, valueStreamer;
|
||||
*this >> keyStreamer >> valueStreamer;
|
||||
streamer = TypeStreamerPointer(new GenericMapTypeStreamer(name, keyStreamer, valueStreamer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
static_cast<GenericTypeStreamer*>(streamer.data())->_weakSelf = streamer;
|
||||
return streamer;
|
||||
}
|
||||
|
||||
QHash<QByteArray, const QMetaObject*>& Bitstream::getMetaObjects() {
|
||||
static QHash<QByteArray, const QMetaObject*> metaObjects;
|
||||
return metaObjects;
|
||||
|
@ -1985,6 +2059,12 @@ void GenericEnumTypeStreamer::write(Bitstream& out, const QVariant& value) const
|
|||
out.write(&intValue, _bits);
|
||||
}
|
||||
|
||||
QVariant GenericEnumTypeStreamer::read(Bitstream& in) const {
|
||||
int intValue = 0;
|
||||
in.read(&intValue, _bits);
|
||||
return QVariant::fromValue(GenericValue(_weakSelf, intValue));
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericEnumTypeStreamer::getCategory() const {
|
||||
return ENUM_CATEGORY;
|
||||
}
|
||||
|
@ -2042,6 +2122,9 @@ GenericStreamableTypeStreamer::GenericStreamableTypeStreamer(const QByteArray& n
|
|||
|
||||
void GenericStreamableTypeStreamer::writeMetadata(Bitstream& out, bool full) const {
|
||||
out << _fields.size();
|
||||
if (_fields.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
foreach (const StreamerNamePair& field, _fields) {
|
||||
out << field.first.data();
|
||||
if (full) {
|
||||
|
@ -2067,6 +2150,14 @@ void GenericStreamableTypeStreamer::write(Bitstream& out, const QVariant& value)
|
|||
}
|
||||
}
|
||||
|
||||
QVariant GenericStreamableTypeStreamer::read(Bitstream& in) const {
|
||||
QVariantList values;
|
||||
foreach (const StreamerNamePair& field, _fields) {
|
||||
values.append(field.first->read(in));
|
||||
}
|
||||
return QVariant::fromValue(GenericValue(_weakSelf, values));
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericStreamableTypeStreamer::getCategory() const {
|
||||
return STREAMABLE_CATEGORY;
|
||||
}
|
||||
|
@ -2124,6 +2215,16 @@ void GenericListTypeStreamer::write(Bitstream& out, const QVariant& value) const
|
|||
}
|
||||
}
|
||||
|
||||
QVariant GenericListTypeStreamer::read(Bitstream& in) const {
|
||||
QVariantList values;
|
||||
int size;
|
||||
in >> size;
|
||||
for (int i = 0; i < size; i++) {
|
||||
values.append(_valueStreamer->read(in));
|
||||
}
|
||||
return QVariant::fromValue(GenericValue(_weakSelf, values));
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericListTypeStreamer::getCategory() const {
|
||||
return LIST_CATEGORY;
|
||||
}
|
||||
|
@ -2218,6 +2319,18 @@ void GenericMapTypeStreamer::write(Bitstream& out, const QVariant& value) const
|
|||
}
|
||||
}
|
||||
|
||||
QVariant GenericMapTypeStreamer::read(Bitstream& in) const {
|
||||
QVariantPairList values;
|
||||
int size;
|
||||
in >> size;
|
||||
for (int i = 0; i < size; i++) {
|
||||
QVariant key = _keyStreamer->read(in);
|
||||
QVariant value = _valueStreamer->read(in);
|
||||
values.append(QVariantPair(key, value));
|
||||
}
|
||||
return QVariant::fromValue(GenericValue(_weakSelf, QVariant::fromValue(values)));
|
||||
}
|
||||
|
||||
TypeStreamer::Category GenericMapTypeStreamer::getCategory() const {
|
||||
return MAP_CATEGORY;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef SharedObjectPointerTemplate<Attribute> AttributePointer;
|
|||
typedef QPair<QByteArray, QByteArray> ScopeNamePair;
|
||||
typedef QPair<QByteArray, int> NameIntPair;
|
||||
typedef QSharedPointer<TypeStreamer> TypeStreamerPointer;
|
||||
typedef QWeakPointer<TypeStreamer> WeakTypeStreamerPointer;
|
||||
typedef QVector<PropertyReader> PropertyReaderVector;
|
||||
typedef QVector<PropertyWriter> PropertyWriterVector;
|
||||
|
||||
|
@ -442,6 +443,8 @@ private slots:
|
|||
|
||||
private:
|
||||
|
||||
TypeStreamerPointer readGenericTypeStreamer(const QByteArray& name, int category);
|
||||
|
||||
QDataStream& _underlying;
|
||||
quint8 _byte;
|
||||
int _position;
|
||||
|
@ -983,9 +986,12 @@ public:
|
|||
|
||||
virtual const char* getName() const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
friend class Bitstream;
|
||||
|
||||
QByteArray _name;
|
||||
WeakTypeStreamerPointer _weakSelf;
|
||||
};
|
||||
|
||||
/// A streamer for generic enums.
|
||||
|
@ -996,6 +1002,7 @@ public:
|
|||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
@ -1071,6 +1078,7 @@ public:
|
|||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
@ -1140,6 +1148,7 @@ public:
|
|||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
@ -1220,6 +1229,7 @@ public:
|
|||
|
||||
virtual void writeMetadata(Bitstream& out, bool full) const;
|
||||
virtual void write(Bitstream& out, const QVariant& value) const;
|
||||
virtual QVariant read(Bitstream& in) const;
|
||||
virtual Category getCategory() const;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue