Commit 578d1869 authored by Orgad Shaneh's avatar Orgad Shaneh Committed by Orgad Shaneh

SynchronousProcess: Replace last QByteArrays with QStrings

Matching \n in a QByteArray is wrong. For example, it detects Ċ (U+010A)
and ਛ (U+0A1B) as end-of-line

Change-Id: I9c03d0b19da3d328e706ff2c89f09713be870f34
Reviewed-by: default avatarOswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent 5da86a07
......@@ -153,9 +153,9 @@ QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessRes
struct ChannelBuffer {
ChannelBuffer();
void clearForRun();
QByteArray linesRead();
QString linesRead();
QByteArray data;
QString data;
bool firstData;
bool bufferedSignalsEnabled;
bool firstBuffer;
......@@ -178,16 +178,15 @@ void ChannelBuffer::clearForRun()
}
/* Check for complete lines read from the device and return them, moving the
* buffer position. This is based on the assumption that '\n' is the new line
* marker in any sane codec. */
QByteArray ChannelBuffer::linesRead()
* buffer position. */
QString ChannelBuffer::linesRead()
{
// Any new lines?
const int lastLineIndex = data.lastIndexOf('\n');
const int lastLineIndex = data.lastIndexOf(QLatin1Char('\n'));
if (lastLineIndex == -1 || lastLineIndex <= bufferPos)
return QByteArray();
return QString();
const int nextBufferPos = lastLineIndex + 1;
const QByteArray lines = data.mid(bufferPos, nextBufferPos - bufferPos);
const QString lines = data.mid(bufferPos, nextBufferPos - bufferPos);
bufferPos = nextBufferPos;
return lines;
}
......@@ -198,6 +197,8 @@ struct SynchronousProcessPrivate {
void clearForRun();
QTextCodec *m_codec;
QTextCodec::ConverterState m_stdOutState;
QTextCodec::ConverterState m_stdErrState;
TerminalControllingProcess m_process;
QTimer m_timer;
QEventLoop m_eventLoop;
......@@ -214,7 +215,7 @@ struct SynchronousProcessPrivate {
};
SynchronousProcessPrivate::SynchronousProcessPrivate() :
m_codec(0),
m_codec(QTextCodec::codecForLocale()),
m_hangTimerCount(0),
m_maxHangTimerCount(defaultMaxHangTimerCount),
m_startFailure(false),
......@@ -269,6 +270,7 @@ int SynchronousProcess::timeout() const
void SynchronousProcess::setCodec(QTextCodec *c)
{
QTC_ASSERT(c, return);
d->m_codec = c;
}
......@@ -380,8 +382,8 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
processStdErr(false);
}
d->m_result.stdOut = convertOutput(d->m_stdOut.data);
d->m_result.stdErr = convertOutput(d->m_stdErr.data);
d->m_result.stdOut = d->m_stdOut.data;
d->m_result.stdErr = d->m_stdErr.data;
d->m_timer.stop();
QApplication::restoreOverrideCursor();
......@@ -474,29 +476,30 @@ void SynchronousProcess::stdErrReady()
processStdErr(true);
}
QString SynchronousProcess::convertOutput(const QByteArray &ba) const
QString SynchronousProcess::convertOutput(const QByteArray &ba,
QTextCodec::ConverterState *state) const
{
return normalizeNewlines(d->m_codec ? d->m_codec->toUnicode(ba)
: QString::fromLocal8Bit(ba.constData(), ba.size()));
return normalizeNewlines(d->m_codec->toUnicode(ba, ba.size(), state));
}
void SynchronousProcess::processStdOut(bool emitSignals)
{
// Handle binary data
const QByteArray ba = d->m_process.readAllStandardOutput();
const QString stdOutput = convertOutput(d->m_process.readAllStandardOutput(),
&d->m_stdOutState);
if (debug > 1)
qDebug() << Q_FUNC_INFO << emitSignals << ba;
if (!ba.isEmpty()) {
d->m_stdOut.data += ba;
qDebug() << Q_FUNC_INFO << emitSignals << stdOutput;
if (!stdOutput.isEmpty()) {
d->m_stdOut.data += stdOutput;
if (emitSignals) {
// Emit binary signals
emit stdOut(ba, d->m_stdOut.firstData);
emit stdOut(stdOutput, d->m_stdOut.firstData);
d->m_stdOut.firstData = false;
// Buffered. Emit complete lines?
if (d->m_stdOut.bufferedSignalsEnabled) {
const QByteArray lines = d->m_stdOut.linesRead();
const QString lines = d->m_stdOut.linesRead();
if (!lines.isEmpty()) {
emit stdOutBuffered(convertOutput(lines), d->m_stdOut.firstBuffer);
emit stdOutBuffered(lines, d->m_stdOut.firstBuffer);
d->m_stdOut.firstBuffer = false;
}
}
......@@ -507,20 +510,21 @@ void SynchronousProcess::processStdOut(bool emitSignals)
void SynchronousProcess::processStdErr(bool emitSignals)
{
// Handle binary data
const QByteArray ba = d->m_process.readAllStandardError();
const QString stdError = convertOutput(d->m_process.readAllStandardError(),
&d->m_stdErrState);
if (debug > 1)
qDebug() << Q_FUNC_INFO << emitSignals << ba;
if (!ba.isEmpty()) {
d->m_stdErr.data += ba;
qDebug() << Q_FUNC_INFO << emitSignals << stdError;
if (!stdError.isEmpty()) {
d->m_stdErr.data += stdError;
if (emitSignals) {
// Emit binary signals
emit stdErr(ba, d->m_stdErr.firstData);
emit stdErr(stdError, d->m_stdErr.firstData);
d->m_stdErr.firstData = false;
if (d->m_stdErr.bufferedSignalsEnabled) {
// Buffered. Emit complete lines?
const QByteArray lines = d->m_stdErr.linesRead();
const QString lines = d->m_stdErr.linesRead();
if (!lines.isEmpty()) {
emit stdErrBuffered(convertOutput(lines), d->m_stdErr.firstBuffer);
emit stdErrBuffered(lines, d->m_stdErr.firstBuffer);
d->m_stdErr.firstBuffer = false;
}
}
......
......@@ -34,11 +34,9 @@
#include <QProcess>
#include <QSharedPointer>
#include <QTextCodec>
QT_BEGIN_NAMESPACE
class QTextCodec;
class QDebug;
QT_END_NAMESPACE
QT_FORWARD_DECLARE_CLASS(QDebug)
namespace Utils {
......@@ -141,8 +139,8 @@ public:
static QString normalizeNewlines(const QString &text);
signals:
void stdOut(const QByteArray &data, bool firstTime);
void stdErr(const QByteArray &data, bool firstTime);
void stdOut(const QString &text, bool firstTime);
void stdErr(const QString &text, bool firstTime);
void stdOutBuffered(const QString &data, bool firstTime);
void stdErrBuffered(const QString &data, bool firstTime);
......@@ -157,7 +155,7 @@ private slots:
private:
void processStdOut(bool emitSignals);
void processStdErr(bool emitSignals);
QString convertOutput(const QByteArray &) const;
QString convertOutput(const QByteArray &, QTextCodec::ConverterState *state) const;
SynchronousProcessPrivate *d;
};
......
......@@ -44,9 +44,9 @@ MainWindow::MainWindow(QWidget *parent) :
QTimer::singleShot(200, this, SLOT(test()));
}
void MainWindow::append(const QByteArray &a)
void MainWindow::append(const QString &s)
{
m_logWindow->appendPlainText(QString::fromLocal8Bit(a));
m_logWindow->appendPlainText(s);
}
void MainWindow::test()
......@@ -58,8 +58,8 @@ void MainWindow::test()
Utils::SynchronousProcess process;
process.setTimeout(2000);
qDebug() << "Async: " << cmd << args;
connect(&process, SIGNAL(stdOut(QByteArray,bool)), this, SLOT(append(QByteArray)));
connect(&process, SIGNAL(stdErr(QByteArray,bool)), this, SLOT(append(QByteArray)));
connect(&process, SIGNAL(stdOut(QString,bool)), this, SLOT(append(QString)));
connect(&process, SIGNAL(stdErr(QString,bool)), this, SLOT(append(QString)));
const Utils::SynchronousProcessResponse resp = process.run(cmd, args);
qDebug() << resp;
}
......@@ -46,7 +46,7 @@ signals:
public slots:
void test();
void append(const QByteArray &a);
void append(const QString &s);
private:
QPlainTextEdit *m_logWindow;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment