[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: Re: Enhancement: KLineBufferedProcess
From: Rolf Eike Beer <kde () opensource ! sf-tec ! de>
Date: 2008-03-11 23:07:20
Message-ID: 200803120007.20935.kde () opensource ! sf-tec ! de
[Download RAW message or body]
[Attachment #2 (multipart/mixed)]
Oswald Buddenhagen wrote:
> On Fri, Mar 07, 2008 at 04:13:40PM +0100, Rolf Eike Beer wrote:
> > The idea behind this class is to receive the data from the process and
> > buffer it. A signal is emitted only if a complete line of data is
> > available.
>
> fwiw, in qt 4.4, the combination of kprocess + qtextstream should work
> reliably.
Well, that would not help anyone who could find arbitrary 8 bit characters in
the output so he needs the result as a QByteArray. For the GPG output I
should be able to write a QTextCodec that handles this stuff. Thanks for the
hint.
Nevertheless I have attached a version that actually works (tested with KGpg).
The other one was a bit hacky since the people at the booth confused me ;)
Eike
["klineprocess.cpp" (text/x-c++src)]
/**
* Copyright (C) 2008 Rolf Eike Beer <kde@opensource.sf-tec.de>
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "klineprocess.h"
class KLineBufferedProcessPrivate
{
public:
KLineBufferedProcessPrivate(KLineBufferedProcess *parent);
//private slot implementations
void _k_receivedStdout();
void _k_receivedStderr();
QByteArray m_stdoutBuffer;
QByteArray m_stderrBuffer;
int m_newlineInStdout;
int m_newlineInStderr;
KLineBufferedProcess *m_parent;
};
KLineBufferedProcessPrivate::KLineBufferedProcessPrivate(KLineBufferedProcess *parent)
{
m_newlineInStdout = -1;
m_newlineInStderr = -1;
m_parent = parent;
}
KLineBufferedProcess::KLineBufferedProcess(QObject *parent)
: KProcess(parent),
d(new KLineBufferedProcessPrivate(this))
{
connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(_k_receivedStdout()));
connect(this, SIGNAL(readyReadStandardError()), this, SLOT(_k_receivedStderr()));
}
KLineBufferedProcess::~KLineBufferedProcess()
{
delete d;
}
#include <KDebug>
void KLineBufferedProcessPrivate::_k_receivedStdout()
{
QByteArray ndata = m_parent->readAllStandardOutput();
int oldBufferSize = m_stdoutBuffer.size();
m_stdoutBuffer.append(ndata);
if (m_newlineInStdout < 0) {
m_newlineInStdout = ndata.indexOf('\n');
if (m_newlineInStdout >= 0) {
m_newlineInStdout += oldBufferSize;
emit m_parent->lineReadyStandardOutput();
}
}
}
void KLineBufferedProcessPrivate::_k_receivedStderr()
{
QByteArray ndata = m_parent->readAllStandardError();
int oldBufferSize = m_stderrBuffer.size();
m_stderrBuffer.append(ndata);
if (m_newlineInStderr < 0) {
m_newlineInStderr = ndata.indexOf('\n');
if (m_newlineInStderr >= 0) {
m_newlineInStderr += oldBufferSize;
emit m_parent->lineReadyStandardError();
}
}
}
bool KLineBufferedProcess::readLineStandardOutput(QByteArray *line)
{
if (d->m_newlineInStdout < 0) {
return false;
}
// don't copy '\n'
*line = d->m_stdoutBuffer.left(d->m_newlineInStdout);
d->m_stdoutBuffer.remove(0, d->m_newlineInStdout + 1);
d->m_newlineInStdout = d->m_stdoutBuffer.indexOf('\n');
return true;
}
bool KLineBufferedProcess::readLineStandardError(QByteArray *line)
{
if (d->m_newlineInStderr < 0) {
return false;
}
// don't copy '\n'
*line = d->m_stderrBuffer.left(d->m_newlineInStderr);
d->m_stderrBuffer.remove(0, d->m_newlineInStderr + 1);
d->m_newlineInStderr = d->m_stderrBuffer.indexOf('\n');
return true;
}
bool KLineBufferedProcess::hasLineStandardOutput()
{
return d->m_newlineInStdout >= 0;
}
bool KLineBufferedProcess::hasLineStandardError()
{
return d->m_newlineInStderr >= 0;
}
#include "klineprocess.moc"
["klineprocess.h" (text/x-c++hdr)]
/**
* Copyright (C) 2008 Rolf Eike Beer <kde@opensource.sf-tec.de>
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef KLINEBUFFEREDPROCESS_H
#define KLINEBUFFEREDPROCESS_H
#include <KProcess>
class QByteArray;
class KLineBufferedProcessPrivate;
/**
* Read output of a process split into lines
*
* This class reads the output of a process and splits it up into lines. This
* is especially useful if you try to parse the output of a command line tool.
*
* \b Usage \n
*
* The class is created and set up like a KProcess. After this you can do
* something like this:
*
* \code
* connect(m_linebufprocess, SIGNAL(lineReadyStandardOutput()), SLOT(dataStdout()));
* ...
* void myobj::dataStdout()
* {
* while (m_linebufprocess->hasLineStandardOutput()) {
* QByteArray line;
* m_linebufprocess->readLineStandardOutput(line);
* ...
* }
* }
* \endcode
*
* Never use the read functionality of KProcess with this class. This class
* needs to read all data from the process into an internal buffer first. If
* you try to use the read funtions of the parent classes you would normally
* get no output at all.
*
* The write functions of the parent classes are not effected. You can use
* them exactly the same way as in KProcess.
*
* @author Rolf Eike Beer
*/
class KLineBufferedProcess : public KProcess
{
Q_OBJECT
friend class KLineBufferedProcessPrivate;
public:
/**
* Constructor
*/
explicit KLineBufferedProcess(QObject *parent = 0);
/**
* Destructor
*/
~KLineBufferedProcess();
/**
* Reads a line of text (excluding '\\n') from stdout.
*
* Use readLineStdout() in response to a lineReadyStdout() signal or
* when hasLineStdout() returns true. You may use it multiple times if
* more than one line of data is available. If no complete line is
* available the content of line is undefined and the function returns
* false.
*
* @param line is used to store the line that was read.
* @return if data was read or not
*/
bool readLineStandardOutput(QByteArray *line);
/**
* Reads a line of text (excluding '\\n') from stderr.
*
* Use readLineStderr() in response to a lineReadyStderr() signal or
* when hasLineStderr() returns true. You may use it multiple times if
* more than one line of data is available. If no complete line is
* available the content of line is undefined and the function returns
* false.
*
* @param line is used to store the line that was read.
* @return if data was read or not
*/
bool readLineStandardError(QByteArray *line);
/**
* Checks if a line is ready on stdout
*
* @return true if a complete line can be read
*/
bool hasLineStandardOutput();
/**
* Checks if a line is ready on stdout
*
* @return true if a complete line can be read
*/
bool hasLineStandardError();
signals:
/**
* Emitted when there is a line of data available from stdout when there was
* previously none.
* There may or may not be more than one line available for reading when this
* signal is emitted.
*/
void lineReadyStandardOutput();
/**
* Emitted when there is a line of data available from stderr when there was
* previously none.
* There may or may not be more than one line available for reading when this
* signal is emitted.
*/
void lineReadyStandardError();
private:
KLineBufferedProcessPrivate* const d;
Q_PRIVATE_SLOT(d, void _k_receivedStdout())
Q_PRIVATE_SLOT(d, void _k_receivedStderr())
};
#endif // GPGPROC_H
["signature.asc" (application/pgp-signature)]
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic