KProcess Line Mode Patch
Ralf Habacker
ralf.habacker at freenet.de
Tue Dec 2 12:51:57 GMT 2008
Thiago Macieira schrieb:
> On Monday 01 December 2008 12:32:08 Ralf Habacker wrote:
>
>> Hi,
>>
>> based on the work described on
>> http://lists.kde.org/?l=kde-core-devel&m=120522889930459&w=2 there is a
>> patch appended which implements a line buffering mode directly in KProcess.
>> The advantage of this approach is that this feature is directly
>> available from kdecore and therefore no additional class located
>> somewhere in the related package source is required.
>>
>> How it works:
>>
>> 1.Line buffering mode ist enabled with the
>>
>> void setOutputLineMode(bool mode);
>>
>> 2.There are new KProcess signals available which indicates available lines.
>>
>> void readyReadLineStandardOutput();
>> void readyReadLineStandardError();
>>
>> 3. The lines could be fetched with
>>
>> QStringList &readLinesStandardOutput(QStringList &out=QStringList());
>> QStringList &readLinesStandardError(QStringList &out=QStringList());
>>
>> 4. non standard line delimiters could be set by
>>
>> void setOutputLineDelimiter(QString &delim=QString());
>>
>> Any comments or objections ?
>>
>
> Yes, I object :-)
>
> A few problems with your approach:
>
> 1) you're using QByteArray for storing the buffer. That's incredibly
> inefficient for large buffers. Imagine that the child program is writing 1MB
> lines: that will cause a lot of memory reallocations and memcpy.
>
> Please use peek() from QIODevice to determine if there's a newline in the
> buffer. You could/should also restrict the length of the search for newline.
> By doing this, you let QIODevice / QProcess manage the buffer, which it does
> using the more-efficient QRingBuffer class (not public)
>
> If you choose not to do this, then I recommend you only read the first line.
> There's no need to keep reading in _k_receivedStdout and _k_receivedStderr if
> you already have one line read.
>
> 2) Note that, with your patch, then you *cannot* use the normal
> QProcess/KProcess functions read(), readLine(), peek(), etc. because you
> drained the buffers. KProcess does not override the QProcess virtuals
> readData() and writeData(), meaning those still operate on QProcess buffers.
>
> In fact, with your patch, you're restricted to the new line mode. The non-line
> mode will not work.
>
> 3) The API you presented:
>
> QStringList &readLinesStandardOutput(QStringList &out=QStringList());
> QStringList &readLinesStandardError(QStringList &out=QStringList());
>
> is IMHO awful. It has no parallel in Qt or KDE core classes. It violates the
> Library Coding Policy by returning a reference. And it takes a reference as a
> parameter, which has a default value(!). Worse yet, you return that temporary
> as a non-const reference.
>
> I think the compiler doesn't even let you write:
> QStringList &out = QStringList();
>
> See:
> $ echo 'class Foo {}; int main() { Foo &foo = Foo(); }' | \
> pipe> /usr/bin/g++ -fsyntax-only -xc++ -
> <stdin>: In function ‘int main()’:
> <stdin>:1: error: invalid initialization of non-const reference of type ‘Foo&’
> from a temporary of type ‘Foo’
>
> Please use QString returns and read one line at a time. That will parallel the
> readLine() function that is already there, by extending it to match what the
> readAll()/readAllStandardError()/readAllStandardOutput() do. That would
> require you to have a canReadLineStandardError and canReadLineStandardOutput()
> already.
>
> 4) Your signals emit only once. The readyRead(), readyReadStandardOutput() and
> and readyReadStandardError() signals emit whenever there's new data.
>
> If you choose to continue with this, your code should emit the signals
> whenever there's a new newline. But I don't see a way of efficiently
> implementing this without direct access to QProcess's buffers -- which
> QProcess won't give you.
>
> 5) Finally, I'm not convinced of the need for this. Why can't people call
> canReadLine() when readyRead() is emitted?
>
I see, it makes no sense to continue this way, so I reject this patch.
> What I'd recommend instead is a line-based reader that works on top of a plain
> QIODevice. That way, you can plug it on a QTcpSocket, QLocalSocket,
> QNetworkReply or KTcpSocket objects as well. (the finished() signal is
> replaced by the readChannelFinished() signal)
>
> This would have the issue, of course, that it doesn't handle a multi-channel
> device like QProcess.
>
>
Appended is a proposal for such a class working with the
QProcess/KProcess output channel.
One question I have is where in the kdelibs such a class could be located ?
Ralf
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: klinebasedreader.patch
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20081202/536319c1/attachment.ksh>
More information about the kde-core-devel
mailing list