PDA

View Full Version : QTextStream::atEnd()



blue.death
8th August 2006, 19:47
Hi guys,
I am going nuts with a strange (for me!) behaviour in QTextStream's atEnd() method.

As far as YOU know, shoundn't the method return true if there is no more data that can be read?
Now what if I call it, it returns true, then I call readLine() and it returns data!

I discovered this quite strange behaviour when trying to read data from a socket in a SMTP client I am writing.

I have something like this:



QTextStream s(mySocketPointer);
bool isAtEnd = s.atEnd(); // <-- returns TRUE!
QString line = s.readLine(); // <-- returns a non empty string!!


To say the truth I use a QTextStream subclass that relies on QTextStream::atEnd() to detect if there is more data to be read in the readLine() method.
The class works well with a standard QTcpSocket (atEnd() returns false!) but I have the problem when using a QtSslSocket (from Trolltech's Qt solutions).

Any clues?

I cannot post any code as the QtSslSocket is only available to users with a commercial license. Sorry :(

PS: It is not a a matter of bad timings between the call to atEnd() and readLine() as I read the data in a slot connected to the socket's readyRead() signal, so I expect to be data in the buffer and that call to atEnd() should return true!!!

wysota
19th August 2006, 12:52
Hi guys,
I am going nuts with a strange (for me!) behaviour in QTextStream's atEnd() method.
This behaviour is completely normal and expected. QTextStream::atEnd() asks the underlying QIODevice to return its atEnd value, so obviously the result of the text stream call depends on the result of the device's call.


As far as YOU know, shoundn't the method return true if there is no more data that can be read?
No. It should return true if there is no more data to read for random access devices. For sequential devices there is no concept of start and end. This is usually not a problem, but for devices which use ::read() to fetch the data, atEnd will always return true, as it has no way to determine whether there is more data to read without reading it. It's explained in QIODevice::atEnd docs.


Now what if I call it, it returns true, then I call readLine() and it returns data!
That's perfectly normal even if we skip the above paragraph. The data could have become available after calling atEnd().


I discovered this quite strange behaviour when trying to read data from a socket in a SMTP client I am writing.
sockets use ::read() to fetch data, so the above mentioned case applies to them.


I have something like this:



QTextStream s(mySocketPointer);
bool isAtEnd = s.atEnd(); // <-- returns TRUE!
QString line = s.readLine(); // <-- returns a non empty string!!


To say the truth I use a QTextStream subclass that relies on QTextStream::atEnd() to detect if there is more data to be read in the readLine() method.

You should use canReadLine() instead of atEnd here.


The class works well with a standard QTcpSocket (atEnd() returns false!) but I have the problem when using a QtSslSocket (from Trolltech's Qt solutions).

Any clues?
Race conditions or buffering (ssl may not decipher another block of data yet, so it returns true, but then data becomes available)... Use canReadLine instead of atEnd


PS: It is not a a matter of bad timings between the call to atEnd() and readLine() as I read the data in a slot connected to the socket's readyRead() signal, so I expect to be data in the buffer and that call to atEnd() should return true!!!
That doesn't have to be the case. The problem may be with the ssl socket implementation and not with the text stream object. Maybe readyRead for the ssl socket is emitted before data is actually ready in the buffer (deciphered).

blue.death
19th August 2006, 20:30
The problem is in the QtSslSocket implementation.
Trolltech has been contacted and the development team has created the task entry # 126453.

Thank you anyway wysota!