535void QIODevice::setOpenMode(QIODeviceBase::OpenMode openMode)
538#if defined QIODEVICE_DEBUG
539 printf(
"%p QIODevice::setOpenMode(0x%x)\n",
this, openMode.toInt());
541 d->openMode = openMode;
542 d->accessMode = QIODevicePrivate::Unset;
543 d->setReadChannelCount(isReadable() ? qMax(d->readChannelCount, 1) : 0);
544 d->setWriteChannelCount(isWritable() ? qMax(d->writeChannelCount, 1) : 0);
668void QIODevice::setCurrentReadChannel(
int channel)
672 if (d->transactionStarted) {
673 checkWarnMessage(
this,
"setReadChannel",
"Failed due to read transaction being in progress");
677#if defined QIODEVICE_DEBUG
678 qDebug(
"%p QIODevice::setCurrentReadChannel(%d), d->currentReadChannel = %d, d->readChannelCount = %d\n",
679 this, channel, d->currentReadChannel, d->readChannelCount);
682 d->setCurrentReadChannel(channel);
688void QIODevicePrivate::setReadChannelCount(
int count)
690 if (count > readBuffers.size()) {
691 readBuffers.reserve(count);
700 while (readBuffers.size() < count)
701 readBuffers.emplace_back(readBufferChunkSize != 0 ? readBufferChunkSize
704 readBuffers.resize(count);
706 readChannelCount = count;
707 setCurrentReadChannel(currentReadChannel);
747void QIODevicePrivate::setWriteChannelCount(
int count)
749 if (count > writeBuffers.size()) {
752 if (writeBufferChunkSize != 0) {
753 writeBuffers.reserve(count);
754 while (writeBuffers.size() < count)
755 writeBuffers.emplace_back(writeBufferChunkSize);
758 writeBuffers.resize(count);
760 writeChannelCount = count;
761 setCurrentWriteChannel(currentWriteChannel);
783bool QIODevice::open(QIODeviceBase::OpenMode mode)
787 d->pos = (mode & Append) ? size() : qint64(0);
788 d->accessMode = QIODevicePrivate::Unset;
789 d->readBuffers.clear();
790 d->writeBuffers.clear();
791 d->setReadChannelCount(isReadable() ? 1 : 0);
792 d->setWriteChannelCount(isWritable() ? 1 : 0);
793 d->errorString.clear();
794#if defined QIODEVICE_DEBUG
795 printf(
"%p QIODevice::open(0x%x)\n",
this, mode.toInt());
1015qint64 QIODevice::read(
char *data, qint64 maxSize)
1018#if defined QIODEVICE_DEBUG
1019 printf(
"%p QIODevice::read(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
1020 this, data, maxSize, d->pos, d->buffer.size());
1024 const bool sequential = d->isSequential();
1027 if (maxSize == 1 && !(sequential && d->transactionStarted)) {
1029 while ((chint = d->buffer.getChar()) != -1) {
1033 char c =
char(uchar(chint));
1034 if (c ==
'\r' && (d->openMode & Text))
1037#if defined QIODEVICE_DEBUG
1038 printf(
"%p \tread 0x%hhx (%c) returning 1 (shortcut)\n",
this,
1039 int(c), isAsciiPrintable(c) ? c :
'?');
1041 if (d->buffer.isEmpty())
1048 const qint64 readBytes = d->read(data, maxSize);
1050#if defined QIODEVICE_DEBUG
1051 printf(
"%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n",
this,
1052 readBytes, d->pos, d->buffer.size());
1054 debugBinaryString(data - readBytes, readBytes);
1063qint64 QIODevicePrivate::read(
char *data, qint64 maxSize,
bool peeking)
1067 const bool buffered = (readBufferChunkSize != 0 && (openMode & QIODevice::Unbuffered) == 0);
1068 const bool sequential = isSequential();
1069 const bool keepDataInBuffer = sequential
1070 ? peeking || transactionStarted
1071 : peeking && buffered;
1072 const qint64 savedPos = pos;
1073 qint64 readSoFar = 0;
1074 bool madeBufferReadsOnly =
true;
1075 bool deviceAtEof =
false;
1076 char *readPtr = data;
1077 qint64 bufferPos = (sequential && transactionStarted) ? transactionPos : Q_INT64_C(0);
1080 qint64 bufferReadChunkSize = keepDataInBuffer
1081 ? buffer.peek(data, maxSize, bufferPos)
1082 : buffer.read(data, maxSize);
1083 if (bufferReadChunkSize > 0) {
1084 bufferPos += bufferReadChunkSize;
1086 pos += bufferReadChunkSize;
1087#if defined QIODEVICE_DEBUG
1088 printf(
"%p \treading %lld bytes from buffer into position %lld\n", q,
1089 bufferReadChunkSize, readSoFar);
1091 readSoFar += bufferReadChunkSize;
1092 data += bufferReadChunkSize;
1093 maxSize -= bufferReadChunkSize;
1096 if (maxSize > 0 && !deviceAtEof) {
1097 qint64 readFromDevice = 0;
1099 if (sequential || pos == devicePos || q->seek(pos)) {
1100 madeBufferReadsOnly =
false;
1101 if ((!buffered || maxSize >= readBufferChunkSize) && !keepDataInBuffer) {
1103 readFromDevice = q->readData(data, maxSize);
1104 deviceAtEof = (readFromDevice != maxSize);
1105#if defined QIODEVICE_DEBUG
1106 printf(
"%p \treading %lld bytes from device (total %lld)\n", q,
1107 readFromDevice, readSoFar);
1109 if (readFromDevice > 0) {
1110 readSoFar += readFromDevice;
1111 data += readFromDevice;
1112 maxSize -= readFromDevice;
1114 pos += readFromDevice;
1115 devicePos += readFromDevice;
1120 const qint64 bytesToBuffer = (!buffered && maxSize < buffer.chunkSize())
1122 : qint64(buffer.chunkSize());
1124 readFromDevice = q->readData(buffer.reserve(bytesToBuffer), bytesToBuffer);
1125 deviceAtEof = (readFromDevice != bytesToBuffer);
1126 buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice));
1127 if (readFromDevice > 0) {
1129 devicePos += readFromDevice;
1130#if defined QIODEVICE_DEBUG
1131 printf(
"%p \treading %lld from device into buffer\n", q,
1138 readFromDevice = -1;
1141 if (readFromDevice < 0 && readSoFar == 0) {
1147 if ((openMode & QIODevice::Text) && readPtr < data) {
1148 const char *endPtr = data;
1151 while (*readPtr !=
'\r') {
1152 if (++readPtr == endPtr)
1156 char *writePtr = readPtr;
1158 while (readPtr < endPtr) {
1159 char ch = *readPtr++;
1180 if (keepDataInBuffer) {
1184 transactionPos = bufferPos;
1185 }
else if (peeking) {
1186 seekBuffer(savedPos);
1189 if (madeBufferReadsOnly && isBufferEmpty())
1190 q->readData(data, 0);
1206QByteArray QIODevice::read(qint64 maxSize)
1209#if defined QIODEVICE_DEBUG
1210 printf(
"%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1211 this, maxSize, d->pos, d->buffer.size());
1219 if (maxSize == d->buffer.nextDataBlockSize() && !d->transactionStarted
1220 && (d->openMode & QIODevice::Text) == 0) {
1221 result = d->buffer.read();
1222 if (!d->isSequential())
1224 if (d->buffer.isEmpty())
1225 readData(
nullptr, 0);
1232 result.resize(qsizetype(maxSize));
1233 qint64 readBytes = d->read(result.data(), result.size());
1238 result.resize(qsizetype(readBytes));
1253QByteArray QIODevice::readAll()
1256#if defined QIODEVICE_DEBUG
1257 printf(
"%p QIODevice::readAll(), d->pos = %lld, d->buffer.size() = %lld\n",
1258 this, d->pos, d->buffer.size());
1264 qint64 readBytes = (d->isSequential() ? Q_INT64_C(0) : size());
1265 if (readBytes == 0) {
1267 qint64 readChunkSize = qMax(qint64(d->buffer.chunkSize()),
1268 d->isSequential() ? (d->buffer.size() - d->transactionPos)
1269 : d->buffer.size());
1272 if (readBytes + readChunkSize >= QByteArray::maxSize()) {
1276 result.resize(readBytes + readChunkSize);
1277 readResult = d->read(result.data() + readBytes, readChunkSize);
1278 if (readResult > 0 || readBytes == 0) {
1279 readBytes += readResult;
1280 readChunkSize = d->buffer.chunkSize();
1282 }
while (readResult > 0);
1285 readBytes -= d->pos;
1286 if (readBytes >= QByteArray::maxSize())
1287 readBytes = QByteArray::maxSize();
1288 result.resize(readBytes);
1289 readBytes = d->read(result.data(), readBytes);
1295 result.resize(qsizetype(readBytes));
1344qint64 QIODevice::readLine(
char *data, qint64 maxSize)
1347#if defined QIODEVICE_DEBUG
1348 printf(
"%p QIODevice::readLine(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
1349 this, data, maxSize, d->pos, d->buffer.size());
1354 const qint64 readBytes = d->readLine(data, maxSize);
1356#if defined QIODEVICE_DEBUG
1357 printf(
"%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n",
1358 this, readBytes, d->pos, d->buffer.size(), size());
1359 debugBinaryString(data, readBytes);
1368qint64 QIODevicePrivate::readLine(
char *data, qint64 maxSize, ReadLineOption option)
1371 const auto appendNullByte = option & ReadLineOption::NullTerminated;
1373 if (appendNullByte) {
1374 Q_ASSERT(maxSize >= 2);
1377 Q_ASSERT(maxSize >= 1);
1380 const bool sequential = isSequential();
1381 const bool keepDataInBuffer = sequential && transactionStarted;
1383 qint64 readSoFar = 0;
1384 if (keepDataInBuffer) {
1385 if (transactionPos < buffer.size()) {
1387 const qint64 i = buffer.indexOf(
'\n', maxSize, transactionPos);
1388 readSoFar = buffer.peek(data, i >= 0 ? (i - transactionPos + 1) : maxSize,
1390 transactionPos += readSoFar;
1391 if (transactionPos == buffer.size())
1392 q->readData(data, 0);
1394 }
else if (!buffer.isEmpty()) {
1396 readSoFar = buffer.readLine(data, maxSize + (appendNullByte ? 1 : 0), option);
1397 if (buffer.isEmpty())
1398 q->readData(data, 0);
1404#if defined QIODEVICE_DEBUG
1405 printf(
"%p \tread from buffer: %lld bytes, last character read: %hhx\n", q,
1406 readSoFar, data[readSoFar - 1]);
1407 debugBinaryString(data, readSoFar);
1409 if (data[readSoFar - 1] ==
'\n') {
1410 if (openMode & QIODevice::Text) {
1412 if (readSoFar > 1 && data[readSoFar - 2] ==
'\r') {
1414 data[readSoFar - 1] =
'\n';
1418 data[readSoFar] =
'\0';
1424 if (pos != devicePos && !sequential && !q->seek(pos))
1426 baseReadLineDataCalled =
false;
1429 qint64 readBytes = keepDataInBuffer
1430 ? q->QIODevice::readLineData(data + readSoFar, maxSize - readSoFar)
1431 : q->readLineData(data + readSoFar, maxSize - readSoFar);
1432#if defined QIODEVICE_DEBUG
1433 printf(
"%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", q,
1434 readBytes, readSoFar);
1435 if (readBytes > 0) {
1436 debugBinaryString(data, readSoFar + readBytes);
1439 if (readBytes < 0) {
1441 data[readSoFar] =
'\0';
1442 return readSoFar ? readSoFar : -1;
1444 readSoFar += readBytes;
1445 if (!baseReadLineDataCalled && !sequential) {
1449 devicePos = qint64(-1);
1452 data[readSoFar] =
'\0';
1454 if (openMode & QIODevice::Text) {
1455 if (readSoFar > 1 && data[readSoFar - 1] ==
'\n' && data[readSoFar - 2] ==
'\r') {
1456 data[readSoFar - 2] =
'\n';
1458 data[readSoFar - 1] =
'\0';
1513bool QIODevice::readLineInto(QByteArray *line, qint64 maxSize)
1516#if defined QIODEVICE_DEBUG
1517 printf(
"%p QIODevice::readLineInto(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1518 this, maxSize, d->pos, d->buffer.size());
1521 auto emptyResultOnFailure = qScopeGuard([line] {
1528 qint64 readBytes = 0;
1532 maxSize = QByteArray::maxSize() - 1;
1536 readBytes = d->skipLine();
1540 line->resize(qsizetype(qMin(maxSize, 1 + readBytes + d->buffer.chunkSize())));
1541 readResult = d->readLine(line->data() + readBytes, line->size() - readBytes);
1542 if (readResult > 0 || readBytes == 0)
1543 readBytes += readResult;
1544 }
while (readResult == d->buffer.chunkSize()
1545 && (*line)[qsizetype(readBytes - 1)] !=
'\n');
1552 readBytes = skip(maxSize);
1554 line->resize(maxSize);
1555 readBytes = d->readLine(line->data(), line->size());
1563 line->resize(readBytes);
1565 emptyResultOnFailure.dismiss();
1601QByteArrayView QIODevice::readLineInto(QSpan<std::byte> buffer)
1604 qint64 maxSize = buffer.size();
1605#if defined QIODEVICE_DEBUG
1606 printf(
"%p QIODevice::readLineInto(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1607 this, qlonglong(maxSize), qlonglong(d->pos), qlonglong(d->buffer.size()));
1613 return buffer.first(0);
1618 const qint64 readBytes = d->readLine(
reinterpret_cast<
char*>(buffer.data()), buffer.size(),
1619 QIODevicePrivate::ReadLineOption::NotNullTerminated);
1624 return buffer.first(readBytes);
1644qint64 QIODevice::readLineData(
char *data, qint64 maxSize)
1647 qint64 readSoFar = 0;
1649 qint64 lastReadReturn = 0;
1650 d->baseReadLineDataCalled =
true;
1652 while (readSoFar < maxSize && (lastReadReturn = read(&c, 1)) == 1) {
1659#if defined QIODEVICE_DEBUG
1660 printf(
"%p QIODevice::readLineData(%p, %lld), d->pos = %lld, d->buffer.size() = %lld, "
1661 "returns %lld\n",
this, data, maxSize, d->pos, d->buffer.size(), readSoFar);
1663 if (lastReadReturn != 1 && readSoFar == 0)
1664 return isSequential() ? lastReadReturn : -1;
1785qint64 QIODevice::write(
const char *data, qint64 maxSize)
1791 const bool sequential = d->isSequential();
1793 if (d->pos != d->devicePos && !sequential && !seek(d->pos))
1797 if (d->openMode & Text) {
1798 const char *endOfData = data + maxSize;
1799 const char *startOfBlock = data;
1801 qint64 writtenSoFar = 0;
1802 const qint64 savedPos = d->pos;
1805 const char *endOfBlock = startOfBlock;
1806 while (endOfBlock < endOfData && *endOfBlock !=
'\n')
1809 qint64 blockSize = endOfBlock - startOfBlock;
1810 if (blockSize > 0) {
1811 qint64 ret = writeData(startOfBlock, blockSize);
1813 if (writtenSoFar && !sequential)
1814 d->buffer.skip(d->pos - savedPos);
1815 return writtenSoFar ? writtenSoFar : ret;
1819 d->devicePos += ret;
1821 writtenSoFar += ret;
1824 if (endOfBlock == endOfData)
1827 qint64 ret = writeData(
"\r\n", 2);
1829 if (writtenSoFar && !sequential)
1830 d->buffer.skip(d->pos - savedPos);
1831 return writtenSoFar ? writtenSoFar : ret;
1835 d->devicePos += ret;
1839 startOfBlock = endOfBlock + 1;
1842 if (writtenSoFar && !sequential)
1843 d->buffer.skip(d->pos - savedPos);
1844 return writtenSoFar;
1848 qint64 written = writeData(data, maxSize);
1849 if (!sequential && written > 0) {
1851 d->devicePos += written;
1852 d->buffer.skip(written);
1978QByteArray QIODevicePrivate::peek(qint64 maxSize)
1980 QByteArray result(maxSize, Qt::Uninitialized);
1982 const qint64 readBytes = read(result.data(), maxSize,
true);
1984 if (readBytes < maxSize) {
1988 result.resize(readBytes);
2089qint64 QIODevice::skip(qint64 maxSize)
2095 const bool sequential = d->isSequential();
2097#if defined QIODEVICE_DEBUG
2098 printf(
"%p QIODevice::skip(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
2099 this, maxSize, d->pos, d->buffer.size());
2102 if ((sequential && d->transactionStarted) || (d->openMode & QIODevice::Text) != 0)
2103 return d->skipByReading(maxSize);
2106 qint64 skippedSoFar = 0;
2107 if (!d->buffer.isEmpty()) {
2108 skippedSoFar = d->buffer.skip(maxSize);
2109#if defined QIODEVICE_DEBUG
2110 printf(
"%p \tskipping %lld bytes in buffer\n",
this, skippedSoFar);
2113 d->pos += skippedSoFar;
2114 if (d->buffer.isEmpty())
2115 readData(
nullptr, 0);
2116 if (skippedSoFar == maxSize)
2117 return skippedSoFar;
2119 maxSize -= skippedSoFar;
2125 const qint64 bytesToSkip = qMin(size() - d->pos, maxSize);
2129 if (bytesToSkip > 0) {
2130 if (!seek(d->pos + bytesToSkip))
2131 return skippedSoFar ? skippedSoFar : Q_INT64_C(-1);
2132 if (bytesToSkip == maxSize)
2133 return skippedSoFar + bytesToSkip;
2135 skippedSoFar += bytesToSkip;
2136 maxSize -= bytesToSkip;
2140 const qint64 skipResult = skipData(maxSize);
2141 if (skippedSoFar == 0)
2144 if (skipResult == -1)
2145 return skippedSoFar;
2147 return skippedSoFar + skipResult;
2153qint64 QIODevicePrivate::skipByReading(qint64 maxSize)
2155 qint64 readSoFar = 0;
2158 const qint64 readBytes = qMin<qint64>(maxSize,
sizeof(dummy));
2159 const qint64 readResult = read(dummy, readBytes);
2162 if (readResult != readBytes) {
2166 if (readResult == -1)
2169 return readSoFar + readResult;
2172 readSoFar += readResult;
2173 maxSize -= readResult;
2174 }
while (maxSize > 0);
2193qint64 QIODevicePrivate::skipLine()
2196 qint64 readSoFar = 0;
2197 qint64 lastReadReturn = 0;
2199 while ((lastReadReturn = read(&c, 1)) == 1) {
2205#if defined QIODEVICE_DEBUG
2206 printf(
"%p QIODevicePrivate::skipLine(), pos = %lld, buffer.size() = %lld, "
2207 "returns %lld\n",
this, pos, buffer.size(), readSoFar);
2210 if (lastReadReturn != 1 && readSoFar == 0)
2211 return isSequential() ? lastReadReturn : -1;
2390 debug <<
"OpenMode(";
2391 QStringList modeList;
2392 if (modes == QIODevice::NotOpen) {
2393 modeList <<
"NotOpen"_L1;
2395 if (modes & QIODevice::ReadOnly)
2396 modeList <<
"ReadOnly"_L1;
2397 if (modes & QIODevice::WriteOnly)
2398 modeList <<
"WriteOnly"_L1;
2399 if (modes & QIODevice::Append)
2400 modeList <<
"Append"_L1;
2401 if (modes & QIODevice::Truncate)
2402 modeList <<
"Truncate"_L1;
2403 if (modes & QIODevice::Text)
2404 modeList <<
"Text"_L1;
2405 if (modes & QIODevice::Unbuffered)
2406 modeList <<
"Unbuffered"_L1;
2408 std::sort(modeList.begin(), modeList.end());
2409 debug << modeList.join(u'|');