Ivailo Monev 2019-05-19 02:06:26 +00:00
parent 977546e00f
commit a0ef87cd2b
7 changed files with 213 additions and 196 deletions

2
README
View file

@ -61,7 +61,7 @@ QTBUG-21548, QTBUG-6133, QTBUG-18188, QTBUG-36767, QTBUG-35387, QTBUG-37035,
QTBUG-28321, QTBUG-21993, QTBUG-26590, QTBUG-2124, QTBUG-20482, QTBUG-41361,
QTBUG-40153, QTBUG-35479, QTBUG-1628, QTBUG-42989, QTBUG-34861, QTBUG-46767,
QTBUG-25114, QTBUG-24672, QTBUG-23524 (WIP), QTBUG-56088, QTBUG-42189,
QTBUG-39285
QTBUG-39285, QTBUG-18173, QTBUG-28968, QTBUG-34336, QTBUG-40974, QTBUG-44286
Unless you use QMake and QDoc porting to Katie or even supporting it along with
Qt4 in the same codebase is trivial and requires only minor changes because

View file

@ -45,12 +45,12 @@
#include "qdatetime.h"
#include "qdiriterator.h"
#include "qset.h"
#include <QtCore/qdebug.h>
#include "qdebug.h"
#include "qcore_unix_p.h"
#ifndef QT_NO_FSFILEENGINE
#include <errno.h>
#include "qcore_unix_p.h"
#include <stdio.h>
#include <stdlib.h>

View file

@ -54,6 +54,8 @@
QT_BEGIN_NAMESPACE
#define QBYTEARRAY_MAX INT_MAX
#ifdef QIODEVICE_DEBUG
void debugBinaryString(const QByteArray &input)
{
@ -97,8 +99,10 @@ inline void debugBinaryString(const char *data, qint64 maxlen)
#define CHECK_WRITABLE(function, returnType) \
do { \
if ((d->openMode & WriteOnly) == 0) { \
if (d->openMode == NotOpen) \
if (d->openMode == NotOpen) { \
qWarning("QIODevice::"#function": device not open"); \
return returnType; \
} \
qWarning("QIODevice::"#function": ReadOnly device"); \
return returnType; \
} \
@ -107,8 +111,10 @@ inline void debugBinaryString(const char *data, qint64 maxlen)
#define CHECK_READABLE(function, returnType) \
do { \
if ((d->openMode & ReadOnly) == 0) { \
if (d->openMode == NotOpen) \
if (d->openMode == NotOpen) { \
qWarning("QIODevice::"#function": device not open"); \
return returnType; \
} \
qWarning("QIODevice::"#function": WriteOnly device"); \
return returnType; \
} \
@ -118,8 +124,7 @@ inline void debugBinaryString(const char *data, qint64 maxlen)
*/
QIODevicePrivate::QIODevicePrivate()
: openMode(QIODevice::NotOpen), buffer(QIODEVICE_BUFFERSIZE),
pos(0), devicePos(0), seqDumpPos(0)
, pPos(&pos), pDevicePos(&devicePos)
pos(0), devicePos(0)
, baseReadLineDataCalled(false)
, firstRead(true)
, accessMode(Unset)
@ -265,9 +270,10 @@ QIODevicePrivate::~QIODevicePrivate()
\value NotOpen The device is not open.
\value ReadOnly The device is open for reading.
\value WriteOnly The device is open for writing.
\value WriteOnly The device is open for writing. Note that this mode implies
Truncate.
\value ReadWrite The device is open for reading and writing.
\value Append The device is opened in append mode, so that all data is
\value Append The device is opened in append mode so that all data is
written to the end of the file.
\value Truncate If possible, the device is truncated before it is opened.
All earlier contents of the device are lost.
@ -582,7 +588,6 @@ void QIODevice::close()
d->openMode = NotOpen;
d->errorString.clear();
d->pos = 0;
d->seqDumpPos = 0;
d->buffer.clear();
d->firstRead = true;
}
@ -604,7 +609,7 @@ qint64 QIODevice::pos() const
{
Q_D(const QIODevice);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::pos() == %d\n", this, int(d->pos));
printf("%p QIODevice::pos() == %lld\n", this, d->pos);
#endif
return d->pos;
}
@ -626,30 +631,34 @@ qint64 QIODevice::size() const
/*!
For random-access devices, this function sets the current position
to \a pos, returning true on success, or false if an error occurred.
For sequential devices, the default behavior is to do nothing and
return false.
For sequential devices, the default behavior is to produce a warning
and return false.
When subclassing QIODevice, you must call QIODevice::seek() at the
start of your function to ensure integrity with QIODevice's
built-in buffer. The base implementation always returns true.
built-in buffer.
\sa pos(), isSequential()
*/
bool QIODevice::seek(qint64 pos)
{
Q_D(QIODevice);
if (d->isSequential()) {
qWarning("QIODevice::seek: Cannot call seek on a sequential device");
return false;
}
if (d->openMode == NotOpen) {
qWarning("QIODevice::seek: The device is not open");
return false;
}
if (pos < 0) {
qWarning("QIODevice::seek: Invalid pos: %d", int(pos));
qWarning("QIODevice::seek: Invalid pos: %lld", pos);
return false;
}
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::seek(%d), before: d->pos = %d, d->buffer.size() = %d\n",
this, int(pos), int(d->pos), d->buffer.size());
printf("%p QIODevice::seek(%lld), before: d->pos = %lld, d->buffer.size() = %lld\n",
this, pos, d->pos, d->buffer.size());
#endif
qint64 offset = pos - d->pos;
@ -658,18 +667,17 @@ bool QIODevice::seek(qint64 pos)
d->devicePos = pos;
}
if (offset < 0
|| offset >= qint64(d->buffer.size()))
if (offset < 0 || offset >= d->buffer.size())
// When seeking backwards, an operation that is only allowed for
// random-access devices, the buffer is cleared. The next read
// operation will then refill the buffer. We can optimize this, if we
// find that seeking backwards becomes a significant performance hit.
d->buffer.clear();
else if (!d->buffer.isEmpty())
d->buffer.skip(int(offset));
d->buffer.skip(offset);
#if defined QIODEVICE_DEBUG
printf("%p \tafter: d->pos == %d, d->buffer.size() == %d\n", this, int(d->pos),
printf("%p \tafter: d->pos == %lld, d->buffer.size() == %lld\n", this, d->pos,
d->buffer.size());
#endif
return true;
@ -691,8 +699,9 @@ bool QIODevice::atEnd() const
{
Q_D(const QIODevice);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %d\n", this, (d->openMode == NotOpen || d->pos == size()) ? "true" : "false",
int(d->openMode), int(d->pos));
printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %lld\n", this,
(d->openMode == NotOpen || d->pos == size()) ? "true" : "false", int(d->openMode),
d->pos);
#endif
return d->openMode == NotOpen || (d->buffer.isEmpty() && bytesAvailable() == 0);
}
@ -766,15 +775,18 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
Q_D(QIODevice);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::read(%p, %d), d->pos = %d, d->buffer.size() = %d\n",
this, data, int(maxSize), int(d->pos), int(d->buffer.size()));
printf("%p QIODevice::read(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, data, maxSize, d->pos, d->buffer.size());
#endif
const bool sequential = d->isSequential();
// Short circuit for getChar()
if (maxSize == 1) {
int chint;
while ((chint = d->buffer.getChar()) != -1) {
++(*d->pPos);
if (!sequential)
++d->pos;
char c = char(uchar(chint));
if (c == '\r' && (d->openMode & Text))
@ -784,28 +796,29 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this,
int(c), isprint(c) ? c : '?');
#endif
if (d->buffer.isEmpty())
readData(data, 0);
return qint64(1);
}
}
CHECK_MAXLEN(read, qint64(-1));
qint64 readSoFar = 0;
bool moreToRead = true;
do {
bool madeBufferReadsOnly = true;
bool deviceAtEof = false;
char *readPtr = data;
forever {
// Try reading from the buffer.
int lastReadChunkSize = d->buffer.read(data, maxSize);
if (lastReadChunkSize > 0) {
*d->pPos += lastReadChunkSize;
readSoFar += lastReadChunkSize;
// fast exit when satisfied by buffer
if (lastReadChunkSize == maxSize && !(d->openMode & Text))
return readSoFar;
data += lastReadChunkSize;
maxSize -= lastReadChunkSize;
qint64 bufferReadChunkSize = d->buffer.read(data, maxSize);
if (bufferReadChunkSize > 0) {
if (!sequential)
d->pos += bufferReadChunkSize;
readSoFar += bufferReadChunkSize;
data += bufferReadChunkSize;
maxSize -= bufferReadChunkSize;
#if defined QIODEVICE_DEBUG
printf("%p \treading %d bytes from buffer into position %d\n", this, lastReadChunkSize,
int(readSoFar) - lastReadChunkSize);
printf("%p \treading %lld bytes from buffer into position %lld\n", this,
bufferReadChunkSize, readSoFar - bufferReadChunkSize);
#endif
} else {
if (d->firstRead) {
@ -813,111 +826,99 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
// for fast pos updates.
CHECK_READABLE(read, qint64(-1));
d->firstRead = false;
if (d->isSequential()) {
d->pPos = &d->seqDumpPos;
d->pDevicePos = &d->seqDumpPos;
}
}
}
if (!maxSize)
return readSoFar;
if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) {
// In buffered mode, we try to fill up the QIODevice buffer before
// we do anything else.
// buffer is empty at this point, try to fill it
int bytesToBuffer = QIODEVICE_BUFFERSIZE;
char *writePointer = d->buffer.reserve(bytesToBuffer);
// Make sure the device is positioned correctly.
if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
return readSoFar ? readSoFar : qint64(-1);
qint64 readFromDevice = readData(writePointer, bytesToBuffer);
d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice)));
if (readFromDevice > 0) {
*d->pDevicePos += readFromDevice;
if (maxSize > 0 && !deviceAtEof) {
qint64 readFromDevice = 0;
// Make sure the device is positioned correctly.
if (sequential || d->pos == d->devicePos || seek(d->pos)) {
madeBufferReadsOnly = false; // fix readData attempt
if (maxSize >= QIODEVICE_BUFFERSIZE || (d->openMode & Unbuffered)) {
// Read big chunk directly to output buffer
readFromDevice = readData(data, maxSize);
deviceAtEof = (readFromDevice != maxSize);
#if defined QIODEVICE_DEBUG
printf("%p \treading %d from device into buffer\n", this, int(readFromDevice));
printf("%p \treading %lld bytes from device (total %lld)\n", this,
readFromDevice, readSoFar);
#endif
if (!d->buffer.isEmpty()) {
lastReadChunkSize = d->buffer.read(data, maxSize);
readSoFar += lastReadChunkSize;
data += lastReadChunkSize;
maxSize -= lastReadChunkSize;
*d->pPos += lastReadChunkSize;
if (readFromDevice > 0) {
readSoFar += readFromDevice;
data += readFromDevice;
maxSize -= readFromDevice;
if (!sequential) {
d->pos += readFromDevice;
d->devicePos += readFromDevice;
}
}
} else {
const qint64 bytesToBuffer = QIODEVICE_BUFFERSIZE;
// Try to fill QIODevice buffer by single read
readFromDevice = readData(d->buffer.reserve(bytesToBuffer), bytesToBuffer);
deviceAtEof = (readFromDevice != bytesToBuffer);
d->buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice));
if (readFromDevice > 0) {
if (!sequential)
d->devicePos += readFromDevice;
#if defined QIODEVICE_DEBUG
printf("%p \treading %d bytes from buffer at position %d\n", this,
lastReadChunkSize, int(readSoFar));
printf("%p \treading %lld from device into buffer\n", this,
readFromDevice);
#endif
continue;
}
}
} else {
readFromDevice = -1;
}
}
// If we need more, try reading from the device.
if (maxSize > 0) {
// Make sure the device is positioned correctly.
if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
return readSoFar ? readSoFar : qint64(-1);
qint64 readFromDevice = readData(data, maxSize);
#if defined QIODEVICE_DEBUG
printf("%p \treading %d bytes from device (total %d)\n", this, int(readFromDevice), int(readSoFar));
#endif
if (readFromDevice == -1 && readSoFar == 0) {
if (readFromDevice < 0 && readSoFar == 0) {
// error and we haven't read anything: return immediately
return -1;
}
if (readFromDevice > 0) {
lastReadChunkSize += int(readFromDevice);
readSoFar += readFromDevice;
data += readFromDevice;
maxSize -= readFromDevice;
*d->pPos += readFromDevice;
*d->pDevicePos += readFromDevice;
return qint64(-1);
}
}
// Best attempt has been made to read data, don't try again except for text mode adjustment below
moreToRead = false;
if (readSoFar && d->openMode & Text) {
char *readPtr = data - lastReadChunkSize;
if ((d->openMode & Text) && readPtr < data) {
const char *endPtr = data;
if (readPtr < endPtr) {
// optimization to avoid initial self-assignment
while (*readPtr != '\r') {
if (++readPtr == endPtr)
return readSoFar;
}
char *writePtr = readPtr;
while (readPtr < endPtr) {
char ch = *readPtr++;
if (ch != '\r')
*writePtr++ = ch;
else {
--readSoFar;
--data;
++maxSize;
}
}
// Make sure we get more data if there is room for more. This
// is very important for when someone seeks to the start of a
// '\r\n' and reads one character - they should get the '\n'.
moreToRead = (readPtr != writePtr);
// optimization to avoid initial self-assignment
while (*readPtr != '\r') {
if (++readPtr == endPtr)
break;
}
char *writePtr = readPtr;
while (readPtr < endPtr) {
char ch = *readPtr++;
if (ch != '\r')
*writePtr++ = ch;
else {
--readSoFar;
--data;
++maxSize;
}
}
// Make sure we get more data if there is room for more. This
// is very important for when someone seeks to the start of a
// '\r\n' and reads one character - they should get the '\n'.
readPtr = data;
continue;
}
} while (moreToRead);
break;
}
#if defined QIODEVICE_DEBUG
printf("%p \treturning %d, d->pos == %d, d->buffer.size() == %d\n", this,
int(readSoFar), int(d->pos), d->buffer.size());
printf("%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n", this,
readSoFar, d->pos, d->buffer.size());
debugBinaryString(data - readSoFar, readSoFar);
#endif
if (madeBufferReadsOnly && d->buffer.isEmpty()) {
d->buffer.clear();
readData(data, 0);
}
return readSoFar;
}
@ -939,15 +940,15 @@ QByteArray QIODevice::read(qint64 maxSize)
CHECK_MAXLEN(read, result);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::read(%d), d->pos = %d, d->buffer.size() = %d\n",
this, int(maxSize), int(d->pos), int(d->buffer.size()));
printf("%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, maxSize, d->pos, d->buffer.size());
#else
Q_UNUSED(d);
#endif
if (maxSize != qint64(int(maxSize))) {
if (quint64(maxSize) >= QBYTEARRAY_MAX) {
qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
maxSize = INT_MAX;
maxSize = QBYTEARRAY_MAX - 1;
}
qint64 readBytes = 0;
@ -989,33 +990,43 @@ QByteArray QIODevice::readAll()
{
Q_D(QIODevice);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::readAll(), d->pos = %d, d->buffer.size() = %d\n",
this, int(d->pos), int(d->buffer.size()));
printf("%p QIODevice::readAll(), d->pos = %lld, d->buffer.size() = %lld\n",
this, d->pos, d->buffer.size());
#endif
QByteArray result;
qint64 readBytes = 0;
const bool sequential = d->isSequential();
// flush internal read buffer
if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
if (quint64(d->buffer.size()) >= QBYTEARRAY_MAX)
return QByteArray();
result = d->buffer.readAll();
readBytes = result.size();
d->pos += readBytes;
if (!sequential)
d->pos += readBytes;
}
qint64 theSize;
if (d->isSequential() || (theSize = size()) == 0) {
if (sequential || (theSize = size()) == 0) {
// Size is unknown, read incrementally.
qint64 readResult;
do {
result.resize(result.size() + QIODEVICE_BUFFERSIZE);
readResult = read(result.data() + readBytes, result.size() - readBytes);
if (quint64(readBytes) + QIODEVICE_BUFFERSIZE >= QBYTEARRAY_MAX) {
// If resize would fail, don't read more, return what we have.
break;
}
result.resize(readBytes + QIODEVICE_BUFFERSIZE);
readResult = read(result.data() + readBytes, QIODEVICE_BUFFERSIZE);
if (readResult > 0 || readBytes == 0)
readBytes += readResult;
} while (readResult > 0);
} else {
// Read it all in one go.
// If resize fails, don't read anything.
if (quint64(readBytes + theSize - d->pos) >= QBYTEARRAY_MAX)
return QByteArray();
result.resize(int(readBytes + theSize - d->pos));
readBytes += read(result.data() + readBytes, result.size() - readBytes);
}
@ -1073,8 +1084,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
}
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::readLine(%p, %d), d->pos = %d, d->buffer.size() = %d\n",
this, data, int(maxSize), int(d->pos), int(d->buffer.size()));
printf("%p QIODevice::readLine(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, data, maxSize, d->pos, d->buffer.size());
#endif
// Leave room for a '\0'
@ -1085,11 +1096,13 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
qint64 readSoFar = 0;
if (!d->buffer.isEmpty()) {
readSoFar = d->buffer.readLine(data, maxSize);
if (d->buffer.isEmpty())
readData(data, 0);
if (!sequential)
d->pos += readSoFar;
#if defined QIODEVICE_DEBUG
printf("%p \tread from buffer: %d bytes, last character read: %hhx\n", this,
int(readSoFar), data[int(readSoFar) - 1]);
printf("%p \tread from buffer: %lld bytes, last character read: %hhx\n", this,
readSoFar, data[readSoFar - 1]);
if (readSoFar)
debugBinaryString(data, int(readSoFar));
#endif
@ -1111,8 +1124,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
d->baseReadLineDataCalled = false;
qint64 readBytes = readLineData(data + readSoFar, maxSize - readSoFar);
#if defined QIODEVICE_DEBUG
printf("%p \tread from readLineData: %d bytes, readSoFar = %d bytes\n", this,
int(readBytes), int(readSoFar));
printf("%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", this,
readBytes, readSoFar);
if (readBytes > 0) {
debugBinaryString(data, int(readSoFar + readBytes));
}
@ -1139,8 +1152,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
}
#if defined QIODEVICE_DEBUG
printf("%p \treturning %d, d->pos = %d, d->buffer.size() = %d, size() = %d\n",
this, int(readSoFar), int(d->pos), d->buffer.size(), int(size()));
printf("%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n",
this, readSoFar, d->pos, d->buffer.size(), size());
debugBinaryString(data, int(readSoFar));
#endif
return readSoFar;
@ -1164,15 +1177,15 @@ QByteArray QIODevice::readLine(qint64 maxSize)
CHECK_MAXLEN(readLine, result);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::readLine(%d), d->pos = %d, d->buffer.size() = %d\n",
this, int(maxSize), int(d->pos), int(d->buffer.size()));
printf("%p QIODevice::readLine(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, maxSize, d->pos, d->buffer.size());
#else
Q_UNUSED(d);
#endif
if (maxSize > INT_MAX) {
if (quint64(maxSize) >= QBYTEARRAY_MAX) {
qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
maxSize = INT_MAX;
maxSize = QBYTEARRAY_MAX - 1;
}
result.resize(int(maxSize));
@ -1180,7 +1193,7 @@ QByteArray QIODevice::readLine(qint64 maxSize)
if (!result.size()) {
// If resize fails or maxSize == 0, read incrementally
if (maxSize == 0)
maxSize = INT_MAX;
maxSize = QBYTEARRAY_MAX - 1;
// The first iteration needs to leave an extra byte for the terminating null
result.resize(1);
@ -1237,8 +1250,8 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize)
}
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::readLineData(%p, %d), d->pos = %d, d->buffer.size() = %d, returns %d\n",
this, data, int(maxSize), int(d->pos), int(d->buffer.size()), int(readSoFar));
printf("%p QIODevice::readLineData(%p, %lld), d->pos = %lld, d->buffer.size() = %lld, "
"returns %lld\n", this, data, maxSize, d->pos, d->buffer.size(), readSoFar);
#endif
if (lastReadReturn != 1 && readSoFar == 0)
return isSequential() ? lastReadReturn : -1;
@ -1381,7 +1394,8 @@ qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
return readBytes;
buffer.ungetBlock(data, readBytes);
*pPos -= readBytes;
if (!isSequential())
pos -= readBytes;
return readBytes;
}
@ -1396,7 +1410,8 @@ QByteArray QIODevicePrivate::peek(qint64 maxSize)
return result;
buffer.ungetBlock(result.constData(), result.size());
*pPos -= result.size();
if (!isSequential())
pos -= result.size();
return result;
}
@ -1569,6 +1584,9 @@ QString QIODevice::errorString() const
all the requested information was read and therefore does not retry reading
if there was a problem.
This function might be called with a maxSize of 0, which can be used to
perform post-reading operations.
\sa read() readLine() writeData()
*/

View file

@ -80,13 +80,13 @@ public:
first = buf;
len = 0;
}
int size() const {
qint64 size() const {
return len;
}
bool isEmpty() const {
return len == 0;
}
void skip(const int n) {
void skip(const qint64 n) {
if (n >= len) {
clear();
} else {
@ -102,25 +102,25 @@ public:
first++;
return ch;
}
int read(char* target, const int size) {
const int r = qMin(size, len);
qint64 read(char* target, const qint64 size) {
const qint64 r = qMin(size, len);
memcpy(target, first, r);
len -= r;
first += r;
return r;
}
int peek(char* target, const int size) {
const int r = qMin(size, len);
qint64 peek(char* target, const qint64 size) {
const qint64 r = qMin(size, len);
memcpy(target, first, r);
return r;
}
char* reserve(const int size) {
char* reserve(const qint64 size) {
makeSpace(size + len, freeSpaceAtEnd);
char* writePtr = first + len;
len += size;
return writePtr;
}
void chop(const int size) {
void chop(const qint64 size) {
if (size >= len) {
clear();
} else {
@ -133,15 +133,15 @@ public:
clear();
return QByteArray(f, l);
}
int readLine(char* target, int size) {
int r = qMin(size, len);
qint64 readLine(char* target, qint64 size) {
qint64 r = qMin(size, len);
char* eol = static_cast<char*>(memchr(first, '\n', r));
if (eol)
r = 1+(eol-first);
memcpy(target, first, r);
len -= r;
first += r;
return int(r);
return r;
}
bool canReadLine() const {
return memchr(first, '\n', len);
@ -155,7 +155,7 @@ public:
len++;
*first = c;
}
void ungetBlock(const char* block, int size) {
void ungetBlock(const char* block, qint64 size) {
if ((first - buf) < size) {
// underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer
makeSpace(len + size, freeSpaceAtStart);
@ -187,7 +187,7 @@ private:
}
// length of the unread data
int len;
qint64 len;
// start of the unread data
char* first;
// the allocated buffer
@ -213,10 +213,6 @@ public:
QIODevicePrivateLinearBuffer buffer;
qint64 pos;
qint64 devicePos;
// these three are for fast position updates during read, avoiding isSequential test
qint64 seqDumpPos;
qint64 *pPos;
qint64 *pDevicePos;
bool baseReadLineDataCalled;
bool firstRead;

View file

@ -39,11 +39,22 @@
**
****************************************************************************/
#include "qprocess.h"
#include "qprocess_p.h"
#include <qdebug.h>
#include <qstring.h>
#include <qbytearray.h>
#include <qelapsedtimer.h>
#include <qcoreapplication.h>
#include <qsocketnotifier.h>
#include <qtimer.h>
#include <qcore_unix_p.h>
//#define QPROCESS_DEBUG
#if defined QPROCESS_DEBUG
#include <qdebug.h>
#include <qstring.h>
#include <ctype.h>
#include <errno.h>
@ -82,17 +93,7 @@ QT_END_NAMESPACE
#endif
#include "qprocess.h"
#include "qprocess_p.h"
#include <qbytearray.h>
#include <qelapsedtimer.h>
#include <qcoreapplication.h>
#include <qsocketnotifier.h>
#include <qtimer.h>
#ifndef QT_NO_PROCESS
extern char **environ;
QT_BEGIN_NAMESPACE
@ -1566,8 +1567,7 @@ bool QProcess::waitForBytesWritten(int msecs)
bool started = waitForStarted(msecs);
if (!started)
return false;
if (msecs != -1)
msecs -= stopWatch.elapsed();
msecs = qt_timeout_value(msecs, stopWatch.elapsed());
}
return d->waitForBytesWritten(msecs);
@ -1603,8 +1603,7 @@ bool QProcess::waitForFinished(int msecs)
bool started = waitForStarted(msecs);
if (!started)
return false;
if (msecs != -1)
msecs -= stopWatch.elapsed();
msecs = qt_timeout_value(msecs, stopWatch.elapsed());
}
return d->waitForFinished(msecs);
@ -1646,6 +1645,8 @@ void QProcess::setupChildProcess()
qint64 QProcess::readData(char *data, qint64 maxlen)
{
Q_D(QProcess);
if (!maxlen)
return 0;
QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
? &d->errorReadBuffer
: &d->outputReadBuffer;

View file

@ -862,19 +862,6 @@ static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout)
return qt_safe_select(nfds, fdread, fdwrite, 0, &tv);
}
/*
Returns the difference between msecs and elapsed. If msecs is -1,
however, -1 is returned.
*/
static int qt_timeout_value(int msecs, int elapsed)
{
if (msecs == -1)
return -1;
int timeout = msecs - elapsed;
return timeout < 0 ? 0 : timeout;
}
bool QProcessPrivate::waitForStarted(int msecs)
{
Q_Q(QProcess);

View file

@ -338,6 +338,21 @@ union qt_semun {
unsigned short *array; /* array for GETALL, SETALL */
};
/*
Returns the difference between msecs and elapsed. If msecs is -1,
however, -1 is returned.
*/
static int qt_timeout_value(int msecs, int elapsed)
{
if (msecs == -1)
return -1;
int timeout = msecs - elapsed;
return timeout < 0 ? 0 : timeout;
}
QT_END_NAMESPACE
#endif