diff options
Diffstat (limited to 'src/corelib/io/qiodevice.cpp')
-rw-r--r-- | src/corelib/io/qiodevice.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 80122eac5e..82fc34c537 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1879,6 +1879,128 @@ QByteArray QIODevice::peek(qint64 maxSize) } /*! + \since 5.11 + + Skips up to \a maxSize bytes from the device. Returns the number of bytes + actually skipped, or -1 on error. + + This function does not wait and only discards the data that is already + available for reading. + + If the device is opened in text mode, end-of-line terminators are + translated to '\n' symbols and count as a single byte identically to the + read() and peek() behavior. + + This function works for all devices, including sequential ones that cannot + seek(). It is optimized to skip unwanted data after a peek() call. + + For random-access devices, skip() can be used to seek forward from the + current position. Negative \a maxSize values are not allowed. + + \sa peek(), seek(), read() +*/ +qint64 QIODevice::skip(qint64 maxSize) +{ + Q_D(QIODevice); + CHECK_MAXLEN(skip, qint64(-1)); + CHECK_READABLE(skip, qint64(-1)); + + const bool sequential = d->isSequential(); + +#if defined QIODEVICE_DEBUG + printf("%p QIODevice::skip(%lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, maxSize, d->pos, d->buffer.size()); +#endif + + if ((sequential && d->transactionStarted) || (d->openMode & QIODevice::Text) != 0) + return d->skipByReading(maxSize); + + // First, skip over any data in the internal buffer. + qint64 skippedSoFar = 0; + if (!d->buffer.isEmpty()) { + skippedSoFar = d->buffer.skip(maxSize); +#if defined QIODEVICE_DEBUG + printf("%p \tskipping %lld bytes in buffer\n", this, skippedSoFar); +#endif + if (!sequential) + d->pos += skippedSoFar; + if (d->buffer.isEmpty()) + readData(nullptr, 0); + if (skippedSoFar == maxSize) + return skippedSoFar; + + maxSize -= skippedSoFar; + } + + // Try to seek on random-access device. At this point, + // the internal read buffer is empty. + if (!sequential) { + const qint64 bytesToSkip = qMin(size() - d->pos, maxSize); + + // If the size is unknown or file position is at the end, + // fall back to reading below. + if (bytesToSkip > 0) { + if (!seek(d->pos + bytesToSkip)) + return skippedSoFar ? skippedSoFar : Q_INT64_C(-1); + if (bytesToSkip == maxSize) + return skippedSoFar + bytesToSkip; + + skippedSoFar += bytesToSkip; + maxSize -= bytesToSkip; + } + } + + const qint64 skipResult = d->skip(maxSize); + if (skippedSoFar == 0) + return skipResult; + + if (skipResult == -1) + return skippedSoFar; + + return skippedSoFar + skipResult; +} + +/*! + \internal +*/ +qint64 QIODevicePrivate::skipByReading(qint64 maxSize) +{ + qint64 readSoFar = 0; + do { + char dummy[4096]; + const qint64 readBytes = qMin<qint64>(maxSize, sizeof(dummy)); + const qint64 readResult = read(dummy, readBytes); + + // Do not try again, if we got less data. + if (readResult != readBytes) { + if (readSoFar == 0) + return readResult; + + if (readResult == -1) + return readSoFar; + + return readSoFar + readResult; + } + + readSoFar += readResult; + maxSize -= readResult; + } while (maxSize > 0); + + return readSoFar; +} + +/*! + \internal +*/ +qint64 QIODevicePrivate::skip(qint64 maxSize) +{ + // Base implementation discards the data by reading into the dummy buffer. + // It's slow, but this works for all types of devices. Subclasses can + // reimplement this function to improve on that. + return skipByReading(maxSize); +} + +/*! Blocks until new data is available for reading and the readyRead() signal has been emitted, or until \a msecs milliseconds have passed. If msecs is -1, this function will not time out. |