520void QIODevice::setOpenMode(QIODeviceBase::OpenMode openMode)
523#if defined QIODEVICE_DEBUG
524 printf(
"%p QIODevice::setOpenMode(0x%x)\n",
this, openMode.toInt());
526 d->openMode = openMode;
527 d->accessMode = QIODevicePrivate::Unset;
528 d->setReadChannelCount(isReadable() ? qMax(d->readChannelCount, 1) : 0);
529 d->setWriteChannelCount(isWritable() ? qMax(d->writeChannelCount, 1) : 0);
653void QIODevice::setCurrentReadChannel(
int channel)
657 if (d->transactionStarted) {
658 checkWarnMessage(
this,
"setReadChannel",
"Failed due to read transaction being in progress");
662#if defined QIODEVICE_DEBUG
663 qDebug(
"%p QIODevice::setCurrentReadChannel(%d), d->currentReadChannel = %d, d->readChannelCount = %d\n",
664 this, channel, d->currentReadChannel, d->readChannelCount);
667 d->setCurrentReadChannel(channel);
673void QIODevicePrivate::setReadChannelCount(
int count)
675 if (count > readBuffers.size()) {
676 readBuffers.reserve(count);
685 while (readBuffers.size() < count)
686 readBuffers.emplace_back(readBufferChunkSize != 0 ? readBufferChunkSize
689 readBuffers.resize(count);
691 readChannelCount = count;
692 setCurrentReadChannel(currentReadChannel);
732void QIODevicePrivate::setWriteChannelCount(
int count)
734 if (count > writeBuffers.size()) {
737 if (writeBufferChunkSize != 0) {
738 writeBuffers.reserve(count);
739 while (writeBuffers.size() < count)
740 writeBuffers.emplace_back(writeBufferChunkSize);
743 writeBuffers.resize(count);
745 writeChannelCount = count;
746 setCurrentWriteChannel(currentWriteChannel);
768bool QIODevice::open(QIODeviceBase::OpenMode mode)
772 d->pos = (mode & Append) ? size() : qint64(0);
773 d->accessMode = QIODevicePrivate::Unset;
774 d->readBuffers.clear();
775 d->writeBuffers.clear();
776 d->setReadChannelCount(isReadable() ? 1 : 0);
777 d->setWriteChannelCount(isWritable() ? 1 : 0);
778 d->errorString.clear();
779#if defined QIODEVICE_DEBUG
780 printf(
"%p QIODevice::open(0x%x)\n",
this, mode.toInt());
1000qint64 QIODevice::read(
char *data, qint64 maxSize)
1003#if defined QIODEVICE_DEBUG
1004 printf(
"%p QIODevice::read(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
1005 this, data, maxSize, d->pos, d->buffer.size());
1009 const bool sequential = d->isSequential();
1012 if (maxSize == 1 && !(sequential && d->transactionStarted)) {
1014 while ((chint = d->buffer.getChar()) != -1) {
1018 char c =
char(uchar(chint));
1019 if (c ==
'\r' && (d->openMode & Text))
1022#if defined QIODEVICE_DEBUG
1023 printf(
"%p \tread 0x%hhx (%c) returning 1 (shortcut)\n",
this,
1024 int(c), isAsciiPrintable(c) ? c :
'?');
1026 if (d->buffer.isEmpty())
1033 const qint64 readBytes = d->read(data, maxSize);
1035#if defined QIODEVICE_DEBUG
1036 printf(
"%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n",
this,
1037 readBytes, d->pos, d->buffer.size());
1039 debugBinaryString(data - readBytes, readBytes);
1048qint64 QIODevicePrivate::read(
char *data, qint64 maxSize,
bool peeking)
1052 const bool buffered = (readBufferChunkSize != 0 && (openMode & QIODevice::Unbuffered) == 0);
1053 const bool sequential = isSequential();
1054 const bool keepDataInBuffer = sequential
1055 ? peeking || transactionStarted
1056 : peeking && buffered;
1057 const qint64 savedPos = pos;
1058 qint64 readSoFar = 0;
1059 bool madeBufferReadsOnly =
true;
1060 bool deviceAtEof =
false;
1061 char *readPtr = data;
1062 qint64 bufferPos = (sequential && transactionStarted) ? transactionPos : Q_INT64_C(0);
1065 qint64 bufferReadChunkSize = keepDataInBuffer
1066 ? buffer.peek(data, maxSize, bufferPos)
1067 : buffer.read(data, maxSize);
1068 if (bufferReadChunkSize > 0) {
1069 bufferPos += bufferReadChunkSize;
1071 pos += bufferReadChunkSize;
1072#if defined QIODEVICE_DEBUG
1073 printf(
"%p \treading %lld bytes from buffer into position %lld\n", q,
1074 bufferReadChunkSize, readSoFar);
1076 readSoFar += bufferReadChunkSize;
1077 data += bufferReadChunkSize;
1078 maxSize -= bufferReadChunkSize;
1081 if (maxSize > 0 && !deviceAtEof) {
1082 qint64 readFromDevice = 0;
1084 if (sequential || pos == devicePos || q->seek(pos)) {
1085 madeBufferReadsOnly =
false;
1086 if ((!buffered || maxSize >= readBufferChunkSize) && !keepDataInBuffer) {
1088 readFromDevice = q->readData(data, maxSize);
1089 deviceAtEof = (readFromDevice != maxSize);
1090#if defined QIODEVICE_DEBUG
1091 printf(
"%p \treading %lld bytes from device (total %lld)\n", q,
1092 readFromDevice, readSoFar);
1094 if (readFromDevice > 0) {
1095 readSoFar += readFromDevice;
1096 data += readFromDevice;
1097 maxSize -= readFromDevice;
1099 pos += readFromDevice;
1100 devicePos += readFromDevice;
1105 const qint64 bytesToBuffer = (!buffered && maxSize < buffer.chunkSize())
1107 : qint64(buffer.chunkSize());
1109 readFromDevice = q->readData(buffer.reserve(bytesToBuffer), bytesToBuffer);
1110 deviceAtEof = (readFromDevice != bytesToBuffer);
1111 buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice));
1112 if (readFromDevice > 0) {
1114 devicePos += readFromDevice;
1115#if defined QIODEVICE_DEBUG
1116 printf(
"%p \treading %lld from device into buffer\n", q,
1123 readFromDevice = -1;
1126 if (readFromDevice < 0 && readSoFar == 0) {
1132 if ((openMode & QIODevice::Text) && readPtr < data) {
1133 const char *endPtr = data;
1136 while (*readPtr !=
'\r') {
1137 if (++readPtr == endPtr)
1141 char *writePtr = readPtr;
1143 while (readPtr < endPtr) {
1144 char ch = *readPtr++;
1165 if (keepDataInBuffer) {
1169 transactionPos = bufferPos;
1170 }
else if (peeking) {
1171 seekBuffer(savedPos);
1174 if (madeBufferReadsOnly && isBufferEmpty())
1175 q->readData(data, 0);
1191QByteArray QIODevice::read(qint64 maxSize)
1194#if defined QIODEVICE_DEBUG
1195 printf(
"%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1196 this, maxSize, d->pos, d->buffer.size());
1204 if (maxSize == d->buffer.nextDataBlockSize() && !d->transactionStarted
1205 && (d->openMode & QIODevice::Text) == 0) {
1206 result = d->buffer.read();
1207 if (!d->isSequential())
1209 if (d->buffer.isEmpty())
1210 readData(
nullptr, 0);
1217 result.resize(qsizetype(maxSize));
1218 qint64 readBytes = d->read(result.data(), result.size());
1223 result.resize(qsizetype(readBytes));
1238QByteArray QIODevice::readAll()
1241#if defined QIODEVICE_DEBUG
1242 printf(
"%p QIODevice::readAll(), d->pos = %lld, d->buffer.size() = %lld\n",
1243 this, d->pos, d->buffer.size());
1249 qint64 readBytes = (d->isSequential() ? Q_INT64_C(0) : size());
1250 if (readBytes == 0) {
1252 qint64 readChunkSize = qMax(qint64(d->buffer.chunkSize()),
1253 d->isSequential() ? (d->buffer.size() - d->transactionPos)
1254 : d->buffer.size());
1257 if (readBytes + readChunkSize >= QByteArray::maxSize()) {
1261 result.resize(readBytes + readChunkSize);
1262 readResult = d->read(result.data() + readBytes, readChunkSize);
1263 if (readResult > 0 || readBytes == 0) {
1264 readBytes += readResult;
1265 readChunkSize = d->buffer.chunkSize();
1267 }
while (readResult > 0);
1270 readBytes -= d->pos;
1271 if (readBytes >= QByteArray::maxSize())
1272 readBytes = QByteArray::maxSize();
1273 result.resize(readBytes);
1274 readBytes = d->read(result.data(), readBytes);
1280 result.resize(qsizetype(readBytes));
1326qint64 QIODevice::readLine(
char *data, qint64 maxSize)
1329#if defined QIODEVICE_DEBUG
1330 printf(
"%p QIODevice::readLine(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
1331 this, data, maxSize, d->pos, d->buffer.size());
1336 const qint64 readBytes = d->readLine(data, maxSize);
1338#if defined QIODEVICE_DEBUG
1339 printf(
"%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n",
1340 this, readBytes, d->pos, d->buffer.size(), size());
1341 debugBinaryString(data, readBytes);
1350qint64 QIODevicePrivate::readLine(
char *data, qint64 maxSize, ReadLineOption option)
1353 const auto appendNullByte = option & ReadLineOption::NullTerminated;
1355 if (appendNullByte) {
1356 Q_ASSERT(maxSize >= 2);
1359 Q_ASSERT(maxSize >= 1);
1362 const bool sequential = isSequential();
1363 const bool keepDataInBuffer = sequential && transactionStarted;
1365 qint64 readSoFar = 0;
1366 if (keepDataInBuffer) {
1367 if (transactionPos < buffer.size()) {
1369 const qint64 i = buffer.indexOf(
'\n', maxSize, transactionPos);
1370 readSoFar = buffer.peek(data, i >= 0 ? (i - transactionPos + 1) : maxSize,
1372 transactionPos += readSoFar;
1373 if (transactionPos == buffer.size())
1374 q->readData(data, 0);
1376 }
else if (!buffer.isEmpty()) {
1378 readSoFar = buffer.readLine(data, maxSize + (appendNullByte ? 1 : 0), option);
1379 if (buffer.isEmpty())
1380 q->readData(data, 0);
1386#if defined QIODEVICE_DEBUG
1387 printf(
"%p \tread from buffer: %lld bytes, last character read: %hhx\n", q,
1388 readSoFar, data[readSoFar - 1]);
1389 debugBinaryString(data, readSoFar);
1391 if (data[readSoFar - 1] ==
'\n') {
1392 if (openMode & QIODevice::Text) {
1394 if (readSoFar > 1 && data[readSoFar - 2] ==
'\r') {
1396 data[readSoFar - 1] =
'\n';
1400 data[readSoFar] =
'\0';
1406 if (pos != devicePos && !sequential && !q->seek(pos))
1408 baseReadLineDataCalled =
false;
1411 qint64 readBytes = keepDataInBuffer
1412 ? q->QIODevice::readLineData(data + readSoFar, maxSize - readSoFar)
1413 : q->readLineData(data + readSoFar, maxSize - readSoFar);
1414#if defined QIODEVICE_DEBUG
1415 printf(
"%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", q,
1416 readBytes, readSoFar);
1417 if (readBytes > 0) {
1418 debugBinaryString(data, readSoFar + readBytes);
1421 if (readBytes < 0) {
1423 data[readSoFar] =
'\0';
1424 return readSoFar ? readSoFar : -1;
1426 readSoFar += readBytes;
1427 if (!baseReadLineDataCalled && !sequential) {
1431 devicePos = qint64(-1);
1434 data[readSoFar] =
'\0';
1436 if (openMode & QIODevice::Text) {
1437 if (readSoFar > 1 && data[readSoFar - 1] ==
'\n' && data[readSoFar - 2] ==
'\r') {
1438 data[readSoFar - 2] =
'\n';
1440 data[readSoFar - 1] =
'\0';
1495bool QIODevice::readLineInto(QByteArray *line, qint64 maxSize)
1498#if defined QIODEVICE_DEBUG
1499 printf(
"%p QIODevice::readLineInto(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1500 this, maxSize, d->pos, d->buffer.size());
1503 auto emptyResultOnFailure = qScopeGuard([line] {
1510 qint64 readBytes = 0;
1514 maxSize = QByteArray::maxSize() - 1;
1518 readBytes = d->skipLine();
1522 line->resize(qsizetype(qMin(maxSize, 1 + readBytes + d->buffer.chunkSize())));
1523 readResult = d->readLine(line->data() + readBytes, line->size() - readBytes);
1524 if (readResult > 0 || readBytes == 0)
1525 readBytes += readResult;
1526 }
while (readResult == d->buffer.chunkSize()
1527 && (*line)[qsizetype(readBytes - 1)] !=
'\n');
1534 readBytes = skip(maxSize);
1536 line->resize(maxSize);
1537 readBytes = d->readLine(line->data(), line->size());
1545 line->resize(readBytes);
1547 emptyResultOnFailure.dismiss();
1583QByteArrayView QIODevice::readLineInto(QSpan<std::byte> buffer)
1586 qint64 maxSize = buffer.size();
1587#if defined QIODEVICE_DEBUG
1588 printf(
"%p QIODevice::readLineInto(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1589 this, qlonglong(maxSize), qlonglong(d->pos), qlonglong(d->buffer.size()));
1595 return buffer.first(0);
1600 const qint64 readBytes = d->readLine(
reinterpret_cast<
char*>(buffer.data()), buffer.size(),
1601 QIODevicePrivate::ReadLineOption::NotNullTerminated);
1606 return buffer.first(readBytes);
1626qint64 QIODevice::readLineData(
char *data, qint64 maxSize)
1629 qint64 readSoFar = 0;
1631 qint64 lastReadReturn = 0;
1632 d->baseReadLineDataCalled =
true;
1634 while (readSoFar < maxSize && (lastReadReturn = read(&c, 1)) == 1) {
1641#if defined QIODEVICE_DEBUG
1642 printf(
"%p QIODevice::readLineData(%p, %lld), d->pos = %lld, d->buffer.size() = %lld, "
1643 "returns %lld\n",
this, data, maxSize, d->pos, d->buffer.size(), readSoFar);
1645 if (lastReadReturn != 1 && readSoFar == 0)
1646 return isSequential() ? lastReadReturn : -1;
1767qint64 QIODevice::write(
const char *data, qint64 maxSize)
1773 const bool sequential = d->isSequential();
1775 if (d->pos != d->devicePos && !sequential && !seek(d->pos))
1779 if (d->openMode & Text) {
1780 const char *endOfData = data + maxSize;
1781 const char *startOfBlock = data;
1783 qint64 writtenSoFar = 0;
1784 const qint64 savedPos = d->pos;
1787 const char *endOfBlock = startOfBlock;
1788 while (endOfBlock < endOfData && *endOfBlock !=
'\n')
1791 qint64 blockSize = endOfBlock - startOfBlock;
1792 if (blockSize > 0) {
1793 qint64 ret = writeData(startOfBlock, blockSize);
1795 if (writtenSoFar && !sequential)
1796 d->buffer.skip(d->pos - savedPos);
1797 return writtenSoFar ? writtenSoFar : ret;
1801 d->devicePos += ret;
1803 writtenSoFar += ret;
1806 if (endOfBlock == endOfData)
1809 qint64 ret = writeData(
"\r\n", 2);
1811 if (writtenSoFar && !sequential)
1812 d->buffer.skip(d->pos - savedPos);
1813 return writtenSoFar ? writtenSoFar : ret;
1817 d->devicePos += ret;
1821 startOfBlock = endOfBlock + 1;
1824 if (writtenSoFar && !sequential)
1825 d->buffer.skip(d->pos - savedPos);
1826 return writtenSoFar;
1830 qint64 written = writeData(data, maxSize);
1831 if (!sequential && written > 0) {
1833 d->devicePos += written;
1834 d->buffer.skip(written);
1960QByteArray QIODevicePrivate::peek(qint64 maxSize)
1962 QByteArray result(maxSize, Qt::Uninitialized);
1964 const qint64 readBytes = read(result.data(), maxSize,
true);
1966 if (readBytes < maxSize) {
1970 result.resize(readBytes);
2067qint64 QIODevice::skip(qint64 maxSize)
2073 const bool sequential = d->isSequential();
2075#if defined QIODEVICE_DEBUG
2076 printf(
"%p QIODevice::skip(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
2077 this, maxSize, d->pos, d->buffer.size());
2080 if ((sequential && d->transactionStarted) || (d->openMode & QIODevice::Text) != 0)
2081 return d->skipByReading(maxSize);
2084 qint64 skippedSoFar = 0;
2085 if (!d->buffer.isEmpty()) {
2086 skippedSoFar = d->buffer.skip(maxSize);
2087#if defined QIODEVICE_DEBUG
2088 printf(
"%p \tskipping %lld bytes in buffer\n",
this, skippedSoFar);
2091 d->pos += skippedSoFar;
2092 if (d->buffer.isEmpty())
2093 readData(
nullptr, 0);
2094 if (skippedSoFar == maxSize)
2095 return skippedSoFar;
2097 maxSize -= skippedSoFar;
2103 const qint64 bytesToSkip = qMin(size() - d->pos, maxSize);
2107 if (bytesToSkip > 0) {
2108 if (!seek(d->pos + bytesToSkip))
2109 return skippedSoFar ? skippedSoFar : Q_INT64_C(-1);
2110 if (bytesToSkip == maxSize)
2111 return skippedSoFar + bytesToSkip;
2113 skippedSoFar += bytesToSkip;
2114 maxSize -= bytesToSkip;
2118 const qint64 skipResult = skipData(maxSize);
2119 if (skippedSoFar == 0)
2122 if (skipResult == -1)
2123 return skippedSoFar;
2125 return skippedSoFar + skipResult;
2131qint64 QIODevicePrivate::skipByReading(qint64 maxSize)
2133 qint64 readSoFar = 0;
2136 const qint64 readBytes = qMin<qint64>(maxSize,
sizeof(dummy));
2137 const qint64 readResult = read(dummy, readBytes);
2140 if (readResult != readBytes) {
2144 if (readResult == -1)
2147 return readSoFar + readResult;
2150 readSoFar += readResult;
2151 maxSize -= readResult;
2152 }
while (maxSize > 0);
2171qint64 QIODevicePrivate::skipLine()
2174 qint64 readSoFar = 0;
2175 qint64 lastReadReturn = 0;
2177 while ((lastReadReturn = read(&c, 1)) == 1) {
2183#if defined QIODEVICE_DEBUG
2184 printf(
"%p QIODevicePrivate::skipLine(), pos = %lld, buffer.size() = %lld, "
2185 "returns %lld\n",
this, pos, buffer.size(), readSoFar);
2188 if (lastReadReturn != 1 && readSoFar == 0)
2189 return isSequential() ? lastReadReturn : -1;
2368 debug <<
"OpenMode(";
2369 QStringList modeList;
2370 if (modes == QIODevice::NotOpen) {
2371 modeList <<
"NotOpen"_L1;
2373 if (modes & QIODevice::ReadOnly)
2374 modeList <<
"ReadOnly"_L1;
2375 if (modes & QIODevice::WriteOnly)
2376 modeList <<
"WriteOnly"_L1;
2377 if (modes & QIODevice::Append)
2378 modeList <<
"Append"_L1;
2379 if (modes & QIODevice::Truncate)
2380 modeList <<
"Truncate"_L1;
2381 if (modes & QIODevice::Text)
2382 modeList <<
"Text"_L1;
2383 if (modes & QIODevice::Unbuffered)
2384 modeList <<
"Unbuffered"_L1;
2386 std::sort(modeList.begin(), modeList.end());
2387 debug << modeList.join(u'|');