mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-09 15:52:27 +02:00
Fixes to, test for metadata streaming.
This commit is contained in:
parent
6d14ad6ab5
commit
eb95b01aa1
4 changed files with 97 additions and 31 deletions
|
@ -107,6 +107,14 @@ Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, QObject
|
|||
_sharedObjectStreamer(*this) {
|
||||
}
|
||||
|
||||
void Bitstream::addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject) {
|
||||
_metaObjectSubstitutions.insert(className, metaObject);
|
||||
}
|
||||
|
||||
void Bitstream::addTypeSubstitution(const QByteArray& typeName, int type) {
|
||||
_typeStreamerSubstitutions.insert(typeName, getTypeStreamers().value(type));
|
||||
}
|
||||
|
||||
const int LAST_BIT_POSITION = BITS_IN_BYTE - 1;
|
||||
|
||||
Bitstream& Bitstream::write(const void* data, int bits, int offset) {
|
||||
|
@ -496,7 +504,10 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) {
|
|||
objectReader = ObjectReader();
|
||||
return *this;
|
||||
}
|
||||
const QMetaObject* metaObject = getMetaObjects().value(className);
|
||||
const QMetaObject* metaObject = _metaObjectSubstitutions.value(className);
|
||||
if (!metaObject) {
|
||||
metaObject = getMetaObjects().value(className);
|
||||
}
|
||||
if (!metaObject) {
|
||||
qWarning() << "Unknown class name: " << className << "\n";
|
||||
}
|
||||
|
@ -523,6 +534,7 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) {
|
|||
// for hash metadata, check the names/types of the properties as well as the name hash against our own class
|
||||
if (_metadataType == HASH_METADATA) {
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
bool matches = true;
|
||||
if (metaObject) {
|
||||
int propertyIndex = 0;
|
||||
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
||||
|
@ -536,21 +548,20 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) {
|
|||
}
|
||||
if (propertyIndex >= properties.size() ||
|
||||
!properties.at(propertyIndex).getReader().matchesExactly(typeStreamer)) {
|
||||
objectReader = ObjectReader(className, metaObject, properties);
|
||||
return *this;
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
hash.addData(property.name(), strlen(property.name()) + 1);
|
||||
propertyIndex++;
|
||||
}
|
||||
if (propertyIndex != properties.size()) {
|
||||
objectReader = ObjectReader(className, metaObject, properties);
|
||||
return *this;
|
||||
matches = false;
|
||||
}
|
||||
}
|
||||
QByteArray localHashResult = hash.result();
|
||||
QByteArray remoteHashResult(localHashResult.size(), 0);
|
||||
read(remoteHashResult.data(), remoteHashResult.size() * BITS_IN_BYTE);
|
||||
if (metaObject && localHashResult == remoteHashResult) {
|
||||
if (metaObject && matches && localHashResult == remoteHashResult) {
|
||||
objectReader = ObjectReader(className, metaObject, getPropertyReaders(metaObject));
|
||||
return *this;
|
||||
}
|
||||
|
@ -589,7 +600,10 @@ Bitstream& Bitstream::operator<(const TypeStreamer* streamer) {
|
|||
Bitstream& Bitstream::operator>(TypeReader& reader) {
|
||||
QByteArray typeName;
|
||||
*this >> typeName;
|
||||
const TypeStreamer* streamer = getTypeStreamers().value(QMetaType::type(typeName.constData()));
|
||||
const TypeStreamer* streamer = _typeStreamerSubstitutions.value(typeName);
|
||||
if (!streamer) {
|
||||
streamer = getTypeStreamers().value(QMetaType::type(typeName.constData()));
|
||||
}
|
||||
if (!streamer) {
|
||||
qWarning() << "Unknown type name: " << typeName << "\n";
|
||||
}
|
||||
|
|
|
@ -222,6 +222,12 @@ public:
|
|||
/// Creates a new bitstream. Note: the stream may be used for reading or writing, but not both.
|
||||
Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA, QObject* parent = NULL);
|
||||
|
||||
/// Substitutes the supplied metaobject for the given class name's default mapping.
|
||||
void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject);
|
||||
|
||||
/// Substitutes the supplied type for the given type name's default mapping.
|
||||
void addTypeSubstitution(const QByteArray& typeName, int type);
|
||||
|
||||
/// Writes a set of bits to the underlying stream.
|
||||
/// \param bits the number of bits to write
|
||||
/// \param offset the offset of the first bit
|
||||
|
@ -363,6 +369,9 @@ private:
|
|||
|
||||
WeakSharedObjectHash _weakSharedObjectHash;
|
||||
|
||||
QHash<QByteArray, const QMetaObject*> _metaObjectSubstitutions;
|
||||
QHash<QByteArray, const TypeStreamer*> _typeStreamerSubstitutions;
|
||||
|
||||
static QHash<QByteArray, const QMetaObject*>& getMetaObjects();
|
||||
static QMultiHash<const QMetaObject*, const QMetaObject*>& getMetaObjectSubClasses();
|
||||
static QHash<int, const TypeStreamer*>& getTypeStreamers();
|
||||
|
|
|
@ -34,23 +34,65 @@ static int streamedBytesReceived = 0;
|
|||
static int sharedObjectsCreated = 0;
|
||||
static int sharedObjectsDestroyed = 0;
|
||||
|
||||
static QByteArray createRandomBytes(int minimumSize, int maximumSize) {
|
||||
QByteArray bytes(randIntInRange(minimumSize, maximumSize), 0);
|
||||
for (int i = 0; i < bytes.size(); i++) {
|
||||
bytes[i] = rand();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static QByteArray createRandomBytes() {
|
||||
const int MIN_BYTES = 4;
|
||||
const int MAX_BYTES = 16;
|
||||
return createRandomBytes(MIN_BYTES, MAX_BYTES);
|
||||
}
|
||||
|
||||
static bool testSerialization(Bitstream::MetadataType metadataType) {
|
||||
QByteArray array;
|
||||
QDataStream outStream(&array, QIODevice::WriteOnly);
|
||||
Bitstream out(outStream, metadataType);
|
||||
SharedObjectPointer testObjectWritten = new TestSharedObjectA(randFloat());
|
||||
out << testObjectWritten;
|
||||
SharedObjectPointer testObjectWrittenA = new TestSharedObjectA(randFloat());
|
||||
out << testObjectWrittenA;
|
||||
SharedObjectPointer testObjectWrittenB = new TestSharedObjectB(randFloat(), createRandomBytes());
|
||||
out << testObjectWrittenB;
|
||||
QByteArray endWritten = "end";
|
||||
out << endWritten;
|
||||
out.flush();
|
||||
|
||||
QDataStream inStream(array);
|
||||
Bitstream in(inStream, metadataType);
|
||||
SharedObjectPointer testObjectRead;
|
||||
in >> testObjectRead;
|
||||
in.addMetaObjectSubstitution("TestSharedObjectA", &TestSharedObjectB::staticMetaObject);
|
||||
in.addMetaObjectSubstitution("TestSharedObjectB", &TestSharedObjectA::staticMetaObject);
|
||||
SharedObjectPointer testObjectReadA, testObjectReadB;
|
||||
in >> testObjectReadA >> testObjectReadB;
|
||||
|
||||
if (!testObjectWritten->equals(testObjectRead)) {
|
||||
QDebug debug = qDebug() << "Read/write mismatch";
|
||||
testObjectWritten->dump(debug);
|
||||
testObjectRead->dump(debug);
|
||||
if (!testObjectReadA || testObjectReadA->metaObject() != &TestSharedObjectB::staticMetaObject) {
|
||||
qDebug() << "Wrong class for A" << testObjectReadA << metadataType;
|
||||
return true;
|
||||
}
|
||||
if (metadataType == Bitstream::FULL_METADATA && static_cast<TestSharedObjectA*>(testObjectWrittenA.data())->getFoo() !=
|
||||
static_cast<TestSharedObjectB*>(testObjectReadA.data())->getFoo()) {
|
||||
QDebug debug = qDebug() << "Failed to transfer shared field from A to B";
|
||||
testObjectWrittenA->dump(debug);
|
||||
testObjectReadA->dump(debug);
|
||||
}
|
||||
|
||||
if (!testObjectReadB || testObjectReadB->metaObject() != &TestSharedObjectA::staticMetaObject) {
|
||||
qDebug() << "Wrong class for B" << testObjectReadB << metadataType;
|
||||
return true;
|
||||
}
|
||||
if (metadataType == Bitstream::FULL_METADATA && static_cast<TestSharedObjectB*>(testObjectWrittenB.data())->getFoo() !=
|
||||
static_cast<TestSharedObjectA*>(testObjectReadB.data())->getFoo()) {
|
||||
QDebug debug = qDebug() << "Failed to transfer shared field from B to A";
|
||||
testObjectWrittenB->dump(debug);
|
||||
testObjectReadB->dump(debug);
|
||||
}
|
||||
|
||||
QByteArray endRead;
|
||||
in >> endRead;
|
||||
if (endWritten != endRead) {
|
||||
qDebug() << "End tag mismatch." << endRead;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -100,20 +142,6 @@ bool MetavoxelTests::run() {
|
|||
return false;
|
||||
}
|
||||
|
||||
static QByteArray createRandomBytes(int minimumSize, int maximumSize) {
|
||||
QByteArray bytes(randIntInRange(minimumSize, maximumSize), 0);
|
||||
for (int i = 0; i < bytes.size(); i++) {
|
||||
bytes[i] = rand();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static QByteArray createRandomBytes() {
|
||||
const int MIN_BYTES = 4;
|
||||
const int MAX_BYTES = 16;
|
||||
return createRandomBytes(MIN_BYTES, MAX_BYTES);
|
||||
}
|
||||
|
||||
static SharedObjectPointer createRandomSharedObject() {
|
||||
switch (randIntInRange(0, 2)) {
|
||||
case 0: return new TestSharedObjectA(randFloat());
|
||||
|
@ -354,7 +382,9 @@ void TestSharedObjectA::setFoo(float foo) {
|
|||
}
|
||||
}
|
||||
|
||||
TestSharedObjectB::TestSharedObjectB() {
|
||||
TestSharedObjectB::TestSharedObjectB(float foo, const QByteArray& bar) :
|
||||
_foo(foo),
|
||||
_bar(bar) {
|
||||
sharedObjectsCreated++;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,11 +89,24 @@ private:
|
|||
/// Another simple shared object.
|
||||
class TestSharedObjectB : public SharedObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float foo READ getFoo WRITE setFoo)
|
||||
Q_PROPERTY(QByteArray bar READ getBar WRITE setBar)
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE TestSharedObjectB();
|
||||
Q_INVOKABLE TestSharedObjectB(float foo = 0.0f, const QByteArray& bar = QByteArray());
|
||||
virtual ~TestSharedObjectB();
|
||||
|
||||
void setFoo(float foo) { _foo = foo; }
|
||||
float getFoo() const { return _foo; }
|
||||
|
||||
void setBar(const QByteArray& bar) { _bar = bar; }
|
||||
const QByteArray& getBar() const { return _bar; }
|
||||
|
||||
private:
|
||||
|
||||
float _foo;
|
||||
QByteArray _bar;
|
||||
};
|
||||
|
||||
/// A simple test message.
|
||||
|
|
Loading…
Reference in a new issue