[Development] Enhancement to QIODevice?

Andrzej Ostruszka andrzej.ostruszka at gmail.com
Mon Sep 14 12:25:20 CEST 2015


Hello all,

I'd like to ask for possibility to enhance a bit QIODevice.

My problem/wish is following.  I'm using QSerialPort and (as all 
QIODevice-s) it is tailored for reading in "lines" ('\n') which is fine 
since most of the time this is exactly what I need.  But I just happen 
to have to deal with an older lock-in device which communicates via 
messages terminated by '\r'.

So what I'm aiming to is to make the "line" (or more generally "packet") 
termination a bit more flexible, that is to allow user to specify the 
delimiter.  Currently I think the only available solution for my wish is 
double buffering - that is to introduce my own buffer that will suck 
everything from QIODevice and allow searching for other delimiter but 
I'd like to do better than that.

 From now on I'll talk about QIODevice only since QSerialPort is 
inheriting from it for the bulk of functionality (and this could also 
benefit QIODevice).

Since '\n' is just hardcoded in QIODevice (actually in buffer used in 
its private part) one option would be to add it as last optional 
parameter to canReadLine() and readLine() with default value '\n'. What 
do you think?

I'm afraid a bit that you might object here:
- we don't want to change that low level functionality to just fit some 
very specific and rare case (true my example is rare - but I can find 
other aplications like e.g. reading pipe delimited values or other)
- this would not be backward compatible (although I don't why)
- being low level would "naturally" push this interface change to all 
classes that inherit from QIODevice and this would be significant change
- in addition to changing code we would have to also change documentation

So the other option that I'd like for you to consider is to enhance 
buffer used for reading in QIODevicePrivate.

Minimal change that I could come up with is:
--8<-----------------------
diff --git i/src/corelib/io/qiodevice_p.h w/src/corelib/io/qiodevice_p.h
index 56a89ab..090e551 100644
--- i/src/corelib/io/qiodevice_p.h
+++ w/src/corelib/io/qiodevice_p.h
@@ -143,6 +143,10 @@ public:
      bool canReadLine() const {
          return memchr(first, '\n', len);
      }
+    qint64 countTo(char c) {
+        char* pos =  static_cast<char*>(memchr(first, c, len));
+        return pos ? 1+(pos-first) : 0;
+    }
      void ungetChar(char c) {
          if (first == buf) {
              // underflow, the existing valid data needs to move to the en
--8<-----------------------
countTo() returns number of bytes one would have to read() in order to 
have first delimiter copied to user data structures (that is it is 
inclusive) and if delimiter is not available than it returns 0.

By using this I can then subclass QSerialPort and implement what I want 
without double buffering.  That way I can also avoid double searching 
for delimiter [1].

Does this kind of suggestion/change has any chance of going through.  In 
other words: would it be a waste of time for me to setup dev env and 
gerrit to try to push something like this?

Best regards
Andrzej Ostruszka

[1] This is "a problem" with the current interface since usually 
QIODevice::canReadLine() and QIODevice::readLine() are used in tandem 
and in readyRead() callback one checks for "canReadLine" before invoking 
readLine() in order to not block if the whole line is not yet available. 
  This pattern means that we are doubly searching for the delimiter.



More information about the Development mailing list