More metadata fixes.

This commit is contained in:
Andrzej Kapolka 2014-03-17 17:21:46 -07:00
parent eb95b01aa1
commit d569802fbc
3 changed files with 48 additions and 22 deletions

View file

@ -31,6 +31,7 @@ REGISTER_SIMPLE_TYPE_STREAMER(QString)
REGISTER_SIMPLE_TYPE_STREAMER(QUrl)
REGISTER_SIMPLE_TYPE_STREAMER(QVariantList)
REGISTER_SIMPLE_TYPE_STREAMER(QVariantHash)
REGISTER_SIMPLE_TYPE_STREAMER(SharedObjectPointer)
// some types don't quite work with our macro
static int vec3Streamer = Bitstream::registerTypeStreamer(qMetaTypeId<glm::vec3>(), new SimpleTypeStreamer<glm::vec3>());
@ -630,29 +631,31 @@ Bitstream& Bitstream::operator>(TypeReader& reader) {
// for hash metadata, check the names/types of the fields as well as the name hash against our own class
if (_metadataType == HASH_METADATA) {
QCryptographicHash hash(QCryptographicHash::Md5);
bool matches = true;
if (streamer) {
const QVector<MetaField>& localFields = streamer->getMetaFields();
if (fieldCount != localFields.size()) {
reader = TypeReader(typeName, streamer, false, fields);
return *this;
}
if (fieldCount == 0) {
reader = TypeReader(typeName, streamer);
return *this;
}
for (int i = 0; i < fieldCount; i++) {
const MetaField& localField = localFields.at(i);
if (!fields.at(i).getReader().matchesExactly(localField.getStreamer())) {
reader = TypeReader(typeName, streamer, false, fields);
matches = false;
} else {
if (fieldCount == 0) {
reader = TypeReader(typeName, streamer);
return *this;
}
hash.addData(localField.getName().constData(), localField.getName().size() + 1);
for (int i = 0; i < fieldCount; i++) {
const MetaField& localField = localFields.at(i);
if (!fields.at(i).getReader().matchesExactly(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 (streamer && localHashResult == remoteHashResult) {
if (streamer && matches && localHashResult == remoteHashResult) {
// since everything is the same, we can use the default streamer
reader = TypeReader(typeName, streamer);
return *this;

View file

@ -589,7 +589,7 @@ public:
/// Macro for registering simple type streamers.
#define REGISTER_SIMPLE_TYPE_STREAMER(x) static int x##Streamer = \
Bitstream::registerTypeStreamer(QMetaType::type(#x), new SimpleTypeStreamer<x>());
Bitstream::registerTypeStreamer(qMetaTypeId<x>(), new SimpleTypeStreamer<x>());
/// Declares the metatype and the streaming operators. The last lines
/// ensure that the generated file will be included in the link phase.

View file

@ -48,6 +48,15 @@ static QByteArray createRandomBytes() {
return createRandomBytes(MIN_BYTES, MAX_BYTES);
}
static TestMessageC createRandomMessageC() {
TestMessageC message;
message.foo = randomBoolean();
message.bar = rand();
message.baz = randFloat();
message.bong.foo = createRandomBytes();
return message;
}
static bool testSerialization(Bitstream::MetadataType metadataType) {
QByteArray array;
QDataStream outStream(&array, QIODevice::WriteOnly);
@ -56,6 +65,8 @@ static bool testSerialization(Bitstream::MetadataType metadataType) {
out << testObjectWrittenA;
SharedObjectPointer testObjectWrittenB = new TestSharedObjectB(randFloat(), createRandomBytes());
out << testObjectWrittenB;
TestMessageC messageWritten = createRandomMessageC();
out << QVariant::fromValue(messageWritten);
QByteArray endWritten = "end";
out << endWritten;
out.flush();
@ -64,8 +75,9 @@ static bool testSerialization(Bitstream::MetadataType metadataType) {
Bitstream in(inStream, metadataType);
in.addMetaObjectSubstitution("TestSharedObjectA", &TestSharedObjectB::staticMetaObject);
in.addMetaObjectSubstitution("TestSharedObjectB", &TestSharedObjectA::staticMetaObject);
SharedObjectPointer testObjectReadA, testObjectReadB;
in >> testObjectReadA >> testObjectReadB;
in.addTypeSubstitution("TestMessageC", TestMessageA::Type);
SharedObjectPointer testObjectReadA;
in >> testObjectReadA;
if (!testObjectReadA || testObjectReadA->metaObject() != &TestSharedObjectB::staticMetaObject) {
qDebug() << "Wrong class for A" << testObjectReadA << metadataType;
@ -76,8 +88,11 @@ static bool testSerialization(Bitstream::MetadataType metadataType) {
QDebug debug = qDebug() << "Failed to transfer shared field from A to B";
testObjectWrittenA->dump(debug);
testObjectReadA->dump(debug);
return true;
}
SharedObjectPointer testObjectReadB;
in >> testObjectReadB;
if (!testObjectReadB || testObjectReadB->metaObject() != &TestSharedObjectA::staticMetaObject) {
qDebug() << "Wrong class for B" << testObjectReadB << metadataType;
return true;
@ -87,6 +102,19 @@ static bool testSerialization(Bitstream::MetadataType metadataType) {
QDebug debug = qDebug() << "Failed to transfer shared field from B to A";
testObjectWrittenB->dump(debug);
testObjectReadB->dump(debug);
return true;
}
QVariant messageRead;
in >> messageRead;
if (!messageRead.isValid() || messageRead.userType() != TestMessageA::Type) {
qDebug() << "Wrong type for message" << messageRead;
return true;
}
if (metadataType == Bitstream::FULL_METADATA && messageWritten.foo != messageRead.value<TestMessageA>().foo) {
QDebug debug = qDebug() << "Failed to transfer shared field between messages" <<
messageWritten.foo << messageRead.value<TestMessageA>().foo;
return true;
}
QByteArray endRead;
@ -192,12 +220,7 @@ static QVariant createRandomMessage() {
}
case 2:
default: {
TestMessageC message;
message.foo = randomBoolean();
message.bar = rand();
message.baz = randFloat();
message.bong.foo = createRandomBytes();
return QVariant::fromValue(message);
return QVariant::fromValue(createRandomMessageC());
}
}
}