Fix KCompressionDevice to work with Qt >= 5.7
ClosedPublic

Authored by aacid on Feb 2 2017, 11:05 PM.

Details

Reviewers
dfaure
Summary

Don't use QIODevice:pos to track our pos, doesn't work.
Call QIODevice::seek at the beginning as documentation says has to be done.

Test Plan

Tests now pass in both Qt 5.6 and Qt 5.7

Diff Detail

Repository
R243 KArchive
Lint
Lint Skipped
Unit
Unit Tests Skipped
aacid updated this revision to Diff 10881.Feb 2 2017, 11:05 PM
aacid retitled this revision from to Fix KCompressionDevice to work with Qt >= 5.7.
aacid updated this object.
aacid edited the test plan for this revision. (Show Details)
aacid set the repository for this revision to R243 KArchive.
Restricted Application added a project: Frameworks. · View Herald TranscriptFeb 2 2017, 11:05 PM
Restricted Application added a subscriber: Frameworks. · View Herald Transcript
aacid updated this revision to Diff 10882.Feb 2 2017, 11:06 PM
aacid updated this object.Feb 2 2017, 11:10 PM
aacid edited the test plan for this revision. (Show Details)

When subclassing QIODevice, you must call QIODevice::seek() at the start of your function to ensure integrity with QIODevice's built-in buffer.

http://doc.qt.io/qt-5/qiodevice.html#seek

For me, i'm not test it, it should be

if (!QIODevice::seek(pos)) {
        return false;
}
qint64 ioIndex = this->pos();
.
.
.
aacid added a comment.Feb 3 2017, 11:32 AM

When subclassing QIODevice, you must call QIODevice::seek() at the start of your function to ensure integrity with QIODevice's built-in buffer.

http://doc.qt.io/qt-5/qiodevice.html#seek

For me, i'm not test it, it should be

if (!QIODevice::seek(pos)) {
        return false;
}
qint64 ioIndex = this->pos();
.
.
.

No

I understand code, it will work now, but to me it's a workaround. What about to call QIODevice::seek(0) in constructor, other unchanged to original code ?

aacid added a comment.Feb 3 2017, 1:17 PM

I understand code, it will work now, but to me it's a workaround.

Why is it a workaround?

What about to call QIODevice::seek(0) in constructor, other unchanged to original code ?

Please, test stuff before suggesting it, saying "No" to every random thing you think may work is not fun.

dfaure accepted this revision.Feb 4 2017, 12:42 PM
dfaure added a reviewer: dfaure.
dfaure added a subscriber: dfaure.

Thanks for the fix.

I had difficulties to understand "Don't use QIODevice:pos to track our pos, doesn't work.", so I investigated a bit and indeed QIODevice has d->pos (the publically visible pos) and d->devicePos (where we are in the actual device, after the last read), so for instance after seeking back we have d->pos==0 and d->devicePos==5.

The problem is, subclasses can't really access d->devicePos, they can only set it by calling QIODevice:seek().

In our own seek() we need to know by how many bytes forward we are moving in terms of devicePos, and we can't know that unless we keep our own member variable indeed. We'd want ioIndex=d->devicePos (at the top of the method, before calling QIODevice::seek), NOT ioIndex=pos(). But we can't access that.

So your patch adds a member variable which duplicates QIODevice::d->devicePos, but there's no other solution without adding more API to QIODevice.

I deem QIODevice API incomplete, and your patch correct given the circumstances.

PS: next time please include the autotest in the commit rather than committing it before, although that's a nice trick to make me jump at the CI failure and look around for the corresponding fix :)

This revision is now accepted and ready to land.Feb 4 2017, 12:42 PM
aacid added a comment.Feb 4 2017, 4:05 PM
In D4422#82977, @dfaure wrote:

So your patch adds a member variable which duplicates QIODevice::d->devicePos, but there's no other solution without adding more API to QIODevice.

I deem QIODevice API incomplete, and your patch correct given the circumstances.

Yeah, one can use the _p.h header that exposes devicePos but i thought depending on the private implementation wasn't cool.

dfaure added a comment.Feb 4 2017, 5:36 PM

Yeah using qiodevice_p.h is out of the question ;)

For info the commit log syntax for autoclosing is
Differential Revision: https://phabricator.kde.org/D4422