QDataStream detect unsupported newer version.



  • Say I compile an app that uses QDataStream to save some stuff like below with Qt 5.11

    // QMap<QString,int> map;
    QDataStream stream(device);
    const qint32 oldVersion = stream.version();
    stream.setVersion(QDataStream::Qt_5_0);
    stream<< oldVersion;
    stream.setVersion(oldVersion);
    stream << map;
    

    The first qint32 in the device is now 17 (QDataStream::Qt_5_11).

    Say I now compile the same app using Qt 5.0 and need to read that data back

    qint32 oldVersion;
    QDataStream stream(device);
    stream.setVersion(QDataStream::Qt_5_0);
    stream >> oldVersion;
    stream.setVersion(oldVersion);
    stream >> map;
    

    Inside Qt I only saw version()< checks so this code will try to read map with the most recent version available and it might crash or just contain gibberish.

    How do I detect the fact that oldVersion here contains a value that is too new to my current Qt version?



  • hi @VRonin ,
    interessting situation. Have you read through the Versioning section of the QDataStream docu?
    http://doc.qt.io/qt-5/qdatastream.html#versioning

    from that I would guess, that writing raw values like

    out << (quint32)0xA0B0C0D0;
    out << (qint32)123;

    are done independently, and the different versions matter only for complex structs, enums etc.



  • @J.Hilk said in QDataStream detect unsupported newer version.:

    only for complex structs

    Yep, that's why I used QMap<QString,int> above, as I think it changed in from different versions (moved from a skip list to a red-black tree)



  • @VRonin
    I'm sorry,
    I totaly missunderstood your question.

    Your issue is, that the read Datastream version may be higher than the QDatstream reading it, may support!

    I think you could potentially work around that with some QT-Macros.

    QT_VERSION_CHECK and QT_VERSION come to mind. Or, as you'll need it at runtime qVersion()


  • Moderators

    @VRonin said in QDataStream detect unsupported newer version.:

    How do I detect the fact that oldVersion here contains a value that is too new to my current Qt version?

    thats what exactly the versioning paragraph mentions (with an example)?
    Write a magic number (or composed Qt-version if you want) as a primitive data-type and then set the version correspondingly.

    If thats Qt-version-magic number is higher than the compiled Qt version you won't be able to read it.

    Edit:
    I should have read @J.Hilk's previous post more clearly!



  • The problem is not writing and reading the version number it's know what's the most recent QDataStream that my program is dynamically linking to. If you distribute anything GPL compatible you have little to no control over the version of Qt used (unless you want to bring in draconic restrictions to linking just because of this).

    Even #ifdef-ing using Qt version, as @J-Hilk suggested, does not work as a program linked to Qt 5.11 should be binary compatible to Qt 5.0 libraries so the user has the liberty of swapping (dynamic) Qt libraries to the earlier version without ever recompiling, in that case my ifdef would still think it's in Qt5.11 land


  • Moderators

    @VRonin said in QDataStream detect unsupported newer version.:

    The problem is not writing and reading the version number it's know what's the most recent QDataStream that my program is dynamically linking to.

    Then compare against QDataStream::Qt_DefaultCompiledVersion
    But this is whats returned by default anyway when you call QDataStream::version() (before overwriting it with an explicit setVersion() call)

    But i am afraid i still don't understand whats your problem is. Either one of us is thinking to complicated :)



  • @VRonin said in QDataStream detect unsupported newer version.:

    The problem is not writing and reading the version number it's know what's the most recent QDataStream that my program is dynamically linking to.

    If that is indeed what your problem/question is ('coz you two keep arguing about that :) ), and you're saying that is dynamic not compile-time, why not have your app create its own temporary QDataStream initially, read it back, and see what the version is? If I've understood correctly....

    Mind you, won't that just be QDataStream::Qt_DefaultCompiledVersion...?



  • @raven-worx said in QDataStream detect unsupported newer version.:

    Then compare against QDataStream::Qt_DefaultCompiledVersion

    That's an enum so as far as I'm aware it's resolved at compile-time

    @raven-worx said in QDataStream detect unsupported newer version.:

    But i am afraid i still don't understand what your problem is.

    • let's pretend for a second that QMap had a massive change in how it was serialised in Qt 5.5
    • I have some code, that is linking to Q 5.11 that serialises a qint32 with the QDataStream::Version that I'm using and the QMap, it will obviously use the new, post-Qt5.5, algorithm
    • Now I have some other code that reads the QMap back. It was built with Qt 5.11 but the user decided to use Qt5.0 dlls (not a problem, they are binary compatible)
      • The new code will read the first qint32 and should be able to detect that the Qt version linked will not be able to de-serialise the QMap correctly because the Qt5.0 dlls don't have that algorithm. My question is how?

    @JonB said in QDataStream detect unsupported newer version.:

    create its own temporary QDataStream initially, read it back, and see what the version is?

    This is the closest to a solution I have at the moment, it looks ugly though!


  • Qt Champions 2017

    @VRonin

    then the easiest solution is to use a feature introduced in Qt 5.11, so neither re-linking nor compiling against older versions give a working program ;)


  • Moderators

    @VRonin said in QDataStream detect unsupported newer version.:

    That's an enum so as far as I'm aware it's resolved at compile-time

    anyway, as i said. It's the initial default value of QDataStream::version()


  • Qt Champions 2017

    @VRonin said in QDataStream detect unsupported newer version.:

    How do I detect the fact that oldVersion here contains a value that is too new to my current Qt version?

    QDataStream stream(device);
    int currentVersion = stream.version(); // Latest possible
    stream.setVersion(QDataStream::Qt_5_0);
    stream >> dataVersion;
    
    if (currentVersion <  dataVersion)
        return; // Ooops I did it again
    
    stream.setVersion(oldVersion);
    stream >> map;
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.