521void QIODevice::setOpenMode(QIODeviceBase::OpenMode openMode)
524#if defined QIODEVICE_DEBUG
525 printf(
"%p QIODevice::setOpenMode(0x%x)\n",
this, openMode.toInt());
527 d->openMode = openMode;
528 d->accessMode = QIODevicePrivate::Unset;
529 d->setReadChannelCount(isReadable() ? qMax(d->readChannelCount, 1) : 0);
530 d->setWriteChannelCount(isWritable() ? qMax(d->writeChannelCount, 1) : 0);
654void QIODevice::setCurrentReadChannel(
int channel)
658 if (d->transactionStarted) {
659 checkWarnMessage(
this,
"setReadChannel",
"Failed due to read transaction being in progress");
663#if defined QIODEVICE_DEBUG
664 qDebug(
"%p QIODevice::setCurrentReadChannel(%d), d->currentReadChannel = %d, d->readChannelCount = %d\n",
665 this, channel, d->currentReadChannel, d->readChannelCount);
668 d->setCurrentReadChannel(channel);
674void QIODevicePrivate::setReadChannelCount(
int count)
676 if (count > readBuffers.size()) {
677 readBuffers.reserve(count);
686 while (readBuffers.size() < count)
687 readBuffers.emplace_back(readBufferChunkSize != 0 ? readBufferChunkSize
690 readBuffers.resize(count);
692 readChannelCount = count;
693 setCurrentReadChannel(currentReadChannel);
733void QIODevicePrivate::setWriteChannelCount(
int count)
735 if (count > writeBuffers.size()) {
738 if (writeBufferChunkSize != 0) {
739 writeBuffers.reserve(count);
740 while (writeBuffers.size() < count)
741 writeBuffers.emplace_back(writeBufferChunkSize);
744 writeBuffers.resize(count);
746 writeChannelCount = count;
747 setCurrentWriteChannel(currentWriteChannel);
769bool QIODevice::open(QIODeviceBase::OpenMode mode)
773 d->pos = (mode & Append) ? size() : qint64(0);
774 d->accessMode = QIODevicePrivate::Unset;
775 d->readBuffers.clear();
776 d->writeBuffers.clear();
777 d->setReadChannelCount(isReadable() ? 1 : 0);
778 d->setWriteChannelCount(isWritable() ? 1 : 0);
779 d->errorString.clear();
780#if defined QIODEVICE_DEBUG
781 printf(
"%p QIODevice::open(0x%x)\n",
this, mode.toInt());
1001qint64 QIODevice::read(
char *data, qint64 maxSize)
1004#if defined QIODEVICE_DEBUG
1005 printf(
"%p QIODevice::read(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
1006 this, data, maxSize, d->pos, d->buffer.size());
1010 const bool sequential = d->isSequential();
1013 if (maxSize == 1 && !(sequential && d->transactionStarted)) {
1015 while ((chint = d->buffer.getChar()) != -1) {
1019 char c =
char(uchar(chint));
1020 if (c ==
'\r' && (d->openMode & Text))
1023#if defined QIODEVICE_DEBUG
1024 printf(
"%p \tread 0x%hhx (%c) returning 1 (shortcut)\n",
this,
1025 int(c), isAsciiPrintable(c) ? c :
'?');
1027 if (d->buffer.isEmpty())
1034 const qint64 readBytes = d->read(data, maxSize);
1036#if defined QIODEVICE_DEBUG
1037 printf(
"%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n",
this,
1038 readBytes, d->pos, d->buffer.size());
1040 debugBinaryString(data - readBytes, readBytes);
1049qint64 QIODevicePrivate::read(
char *data, qint64 maxSize,
bool peeking)
1053 const bool buffered = (readBufferChunkSize != 0 && (openMode & QIODevice::Unbuffered) == 0);
1054 const bool sequential = isSequential();
1055 const bool keepDataInBuffer = sequential
1056 ? peeking || transactionStarted
1057 : peeking && buffered;
1058 const qint64 savedPos = pos;
1059 qint64 readSoFar = 0;
1060 bool madeBufferReadsOnly =
true;
1061 bool deviceAtEof =
false;
1062 char *readPtr = data;
1063 qint64 bufferPos = (sequential && transactionStarted) ? transactionPos : Q_INT64_C(0);
1066 qint64 bufferReadChunkSize = keepDataInBuffer
1067 ? buffer.peek(data, maxSize, bufferPos)
1068 : buffer.read(data, maxSize);
1069 if (bufferReadChunkSize > 0) {
1070 bufferPos += bufferReadChunkSize;
1072 pos += bufferReadChunkSize;
1073#if defined QIODEVICE_DEBUG
1074 printf(
"%p \treading %lld bytes from buffer into position %lld\n", q,
1075 bufferReadChunkSize, readSoFar);
1077 readSoFar += bufferReadChunkSize;
1078 data += bufferReadChunkSize;
1079 maxSize -= bufferReadChunkSize;
1082 if (maxSize > 0 && !deviceAtEof) {
1083 qint64 readFromDevice = 0;
1085 if (sequential || pos == devicePos || q->seek(pos)) {
1086 madeBufferReadsOnly =
false;
1087 if ((!buffered || maxSize >= readBufferChunkSize) && !keepDataInBuffer) {
1089 readFromDevice = q->readData(data, maxSize);
1090 deviceAtEof = (readFromDevice != maxSize);
1091#if defined QIODEVICE_DEBUG
1092 printf(
"%p \treading %lld bytes from device (total %lld)\n", q,
1093 readFromDevice, readSoFar);
1095 if (readFromDevice > 0) {
1096 readSoFar += readFromDevice;
1097 data += readFromDevice;
1098 maxSize -= readFromDevice;
1100 pos += readFromDevice;
1101 devicePos += readFromDevice;
1106 const qint64 bytesToBuffer = (!buffered && maxSize < buffer.chunkSize())
1108 : qint64(buffer.chunkSize());
1110 readFromDevice = q->readData(buffer.reserve(bytesToBuffer), bytesToBuffer);
1111 deviceAtEof = (readFromDevice != bytesToBuffer);
1112 buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice));
1113 if (readFromDevice > 0) {
1115 devicePos += readFromDevice;
1116#if defined QIODEVICE_DEBUG
1117 printf(
"%p \treading %lld from device into buffer\n", q,
1124 readFromDevice = -1;
1127 if (readFromDevice < 0 && readSoFar == 0) {
1133 if ((openMode & QIODevice::Text) && readPtr < data) {
1134 const char *endPtr = data;
1137 while (*readPtr !=
'\r') {
1138 if (++readPtr == endPtr)
1142 char *writePtr = readPtr;
1144 while (readPtr < endPtr) {
1145 char ch = *readPtr++;
1166 if (keepDataInBuffer) {
1170 transactionPos = bufferPos;
1171 }
else if (peeking) {
1172 seekBuffer(savedPos);
1175 if (madeBufferReadsOnly && isBufferEmpty())
1176 q->readData(data, 0);
1192QByteArray QIODevice::read(qint64 maxSize)
1195#if defined QIODEVICE_DEBUG
1196 printf(
"%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1197 this, maxSize, d->pos, d->buffer.size());
1205 if (maxSize == d->buffer.nextDataBlockSize() && !d->transactionStarted
1206 && (d->openMode & QIODevice::Text) == 0) {
1207 result = d->buffer.read();
1208 if (!d->isSequential())
1210 if (d->buffer.isEmpty())
1211 readData(
nullptr, 0);
1218 result.resize(qsizetype(maxSize));
1219 qint64 readBytes = d->read(result.data(), result.size());
1224 result.resize(qsizetype(readBytes));
1239QByteArray QIODevice::readAll()
1242#if defined QIODEVICE_DEBUG
1243 printf(
"%p QIODevice::readAll(), d->pos = %lld, d->buffer.size() = %lld\n",
1244 this, d->pos, d->buffer.size());
1250 qint64 readBytes = (d->isSequential() ? Q_INT64_C(0) : size());
1251 if (readBytes == 0) {
1253 qint64 readChunkSize = qMax(qint64(d->buffer.chunkSize()),
1254 d->isSequential() ? (d->buffer.size() - d->transactionPos)
1255 : d->buffer.size());
1258 if (readBytes + readChunkSize >= QByteArray::maxSize()) {
1262 result.resize(readBytes + readChunkSize);
1263 readResult = d->read(result.data() + readBytes, readChunkSize);
1264 if (readResult > 0 || readBytes == 0) {
1265 readBytes += readResult;
1266 readChunkSize = d->buffer.chunkSize();
1268 }
while (readResult > 0);
1271 readBytes -= d->pos;
1272 if (readBytes >= QByteArray::maxSize())
1273 readBytes = QByteArray::maxSize();
1274 result.resize(readBytes);
1275 readBytes = d->read(result.data(), readBytes);
1281 result.resize(qsizetype(readBytes));
1330qint64 QIODevice::readLine(
char *data, qint64 maxSize)
1333#if defined QIODEVICE_DEBUG
1334 printf(
"%p QIODevice::readLine(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
1335 this, data, maxSize, d->pos, d->buffer.size());
1340 const qint64 readBytes = d->readLine(data, maxSize);
1342#if defined QIODEVICE_DEBUG
1343 printf(
"%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n",
1344 this, readBytes, d->pos, d->buffer.size(), size());
1345 debugBinaryString(data, readBytes);
1354qint64 QIODevicePrivate::readLine(
char *data, qint64 maxSize, ReadLineOption option)
1357 const auto appendNullByte = option & ReadLineOption::NullTerminated;
1359 if (appendNullByte) {
1360 Q_ASSERT(maxSize >= 2);
1363 Q_ASSERT(maxSize >= 1);
1366 const bool sequential = isSequential();
1367 const bool keepDataInBuffer = sequential && transactionStarted;
1369 qint64 readSoFar = 0;
1370 if (keepDataInBuffer) {
1371 if (transactionPos < buffer.size()) {
1373 const qint64 i = buffer.indexOf(
'\n', maxSize, transactionPos);
1374 readSoFar = buffer.peek(data, i >= 0 ? (i - transactionPos + 1) : maxSize,
1376 transactionPos += readSoFar;
1377 if (transactionPos == buffer.size())
1378 q->readData(data, 0);
1380 }
else if (!buffer.isEmpty()) {
1382 readSoFar = buffer.readLine(data, maxSize + (appendNullByte ? 1 : 0), option);
1383 if (buffer.isEmpty())
1384 q->readData(data, 0);
1390#if defined QIODEVICE_DEBUG
1391 printf(
"%p \tread from buffer: %lld bytes, last character read: %hhx\n", q,
1392 readSoFar, data[readSoFar - 1]);
1393 debugBinaryString(data, readSoFar);
1395 if (data[readSoFar - 1] ==
'\n') {
1396 if (openMode & QIODevice::Text) {
1398 if (readSoFar > 1 && data[readSoFar - 2] ==
'\r') {
1400 data[readSoFar - 1] =
'\n';
1404 data[readSoFar] =
'\0';
1410 if (pos != devicePos && !sequential && !q->seek(pos))
1412 baseReadLineDataCalled =
false;
1415 qint64 readBytes = keepDataInBuffer
1416 ? q->QIODevice::readLineData(data + readSoFar, maxSize - readSoFar)
1417 : q->readLineData(data + readSoFar, maxSize - readSoFar);
1418#if defined QIODEVICE_DEBUG
1419 printf(
"%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", q,
1420 readBytes, readSoFar);
1421 if (readBytes > 0) {
1422 debugBinaryString(data, readSoFar + readBytes);
1425 if (readBytes < 0) {
1427 data[readSoFar] =
'\0';
1428 return readSoFar ? readSoFar : -1;
1430 readSoFar += readBytes;
1431 if (!baseReadLineDataCalled && !sequential) {
1435 devicePos = qint64(-1);
1438 data[readSoFar] =
'\0';
1440 if (openMode & QIODevice::Text) {
1441 if (readSoFar > 1 && data[readSoFar - 1] ==
'\n' && data[readSoFar - 2] ==
'\r') {
1442 data[readSoFar - 2] =
'\n';
1444 data[readSoFar - 1] =
'\0';
1499bool QIODevice::readLineInto(QByteArray *line, qint64 maxSize)
1502#if defined QIODEVICE_DEBUG
1503 printf(
"%p QIODevice::readLineInto(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1504 this, maxSize, d->pos, d->buffer.size());
1507 auto emptyResultOnFailure = qScopeGuard([line] {
1514 qint64 readBytes = 0;
1518 maxSize = QByteArray::maxSize() - 1;
1522 readBytes = d->skipLine();
1526 line->resize(qsizetype(qMin(maxSize, 1 + readBytes + d->buffer.chunkSize())));
1527 readResult = d->readLine(line->data() + readBytes, line->size() - readBytes);
1528 if (readResult > 0 || readBytes == 0)
1529 readBytes += readResult;
1530 }
while (readResult == d->buffer.chunkSize()
1531 && (*line)[qsizetype(readBytes - 1)] !=
'\n');
1538 readBytes = skip(maxSize);
1540 line->resize(maxSize);
1541 readBytes = d->readLine(line->data(), line->size());
1549 line->resize(readBytes);
1551 emptyResultOnFailure.dismiss();
1587QByteArrayView QIODevice::readLineInto(QSpan<std::byte> buffer)
1590 qint64 maxSize = buffer.size();
1591#if defined QIODEVICE_DEBUG
1592 printf(
"%p QIODevice::readLineInto(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
1593 this, qlonglong(maxSize), qlonglong(d->pos), qlonglong(d->buffer.size()));
1599 return buffer.first(0);
1604 const qint64 readBytes = d->readLine(
reinterpret_cast<
char*>(buffer.data()), buffer.size(),
1605 QIODevicePrivate::ReadLineOption::NotNullTerminated);
1610 return buffer.first(readBytes);
1630qint64 QIODevice::readLineData(
char *data, qint64 maxSize)
1633 qint64 readSoFar = 0;
1635 qint64 lastReadReturn = 0;
1636 d->baseReadLineDataCalled =
true;
1638 while (readSoFar < maxSize && (lastReadReturn = read(&c, 1)) == 1) {
1645#if defined QIODEVICE_DEBUG
1646 printf(
"%p QIODevice::readLineData(%p, %lld), d->pos = %lld, d->buffer.size() = %lld, "
1647 "returns %lld\n",
this, data, maxSize, d->pos, d->buffer.size(), readSoFar);
1649 if (lastReadReturn != 1 && readSoFar == 0)
1650 return isSequential() ? lastReadReturn : -1;
1771qint64 QIODevice::write(
const char *data, qint64 maxSize)
1777 const bool sequential = d->isSequential();
1779 if (d->pos != d->devicePos && !sequential && !seek(d->pos))
1783 if (d->openMode & Text) {
1784 const char *endOfData = data + maxSize;
1785 const char *startOfBlock = data;
1787 qint64 writtenSoFar = 0;
1788 const qint64 savedPos = d->pos;
1791 const char *endOfBlock = startOfBlock;
1792 while (endOfBlock < endOfData && *endOfBlock !=
'\n')
1795 qint64 blockSize = endOfBlock - startOfBlock;
1796 if (blockSize > 0) {
1797 qint64 ret = writeData(startOfBlock, blockSize);
1799 if (writtenSoFar && !sequential)
1800 d->buffer.skip(d->pos - savedPos);
1801 return writtenSoFar ? writtenSoFar : ret;
1805 d->devicePos += ret;
1807 writtenSoFar += ret;
1810 if (endOfBlock == endOfData)
1813 qint64 ret = writeData(
"\r\n", 2);
1815 if (writtenSoFar && !sequential)
1816 d->buffer.skip(d->pos - savedPos);
1817 return writtenSoFar ? writtenSoFar : ret;
1821 d->devicePos += ret;
1825 startOfBlock = endOfBlock + 1;
1828 if (writtenSoFar && !sequential)
1829 d->buffer.skip(d->pos - savedPos);
1830 return writtenSoFar;
1834 qint64 written = writeData(data, maxSize);
1835 if (!sequential && written > 0) {
1837 d->devicePos += written;
1838 d->buffer.skip(written);
1964QByteArray QIODevicePrivate::peek(qint64 maxSize)
1966 QByteArray result(maxSize, Qt::Uninitialized);
1968 const qint64 readBytes = read(result.data(), maxSize,
true);
1970 if (readBytes < maxSize) {
1974 result.resize(readBytes);
2075qint64 QIODevice::skip(qint64 maxSize)
2081 const bool sequential = d->isSequential();
2083#if defined QIODEVICE_DEBUG
2084 printf(
"%p QIODevice::skip(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
2085 this, maxSize, d->pos, d->buffer.size());
2088 if ((sequential && d->transactionStarted) || (d->openMode & QIODevice::Text) != 0)
2089 return d->skipByReading(maxSize);
2092 qint64 skippedSoFar = 0;
2093 if (!d->buffer.isEmpty()) {
2094 skippedSoFar = d->buffer.skip(maxSize);
2095#if defined QIODEVICE_DEBUG
2096 printf(
"%p \tskipping %lld bytes in buffer\n",
this, skippedSoFar);
2099 d->pos += skippedSoFar;
2100 if (d->buffer.isEmpty())
2101 readData(
nullptr, 0);
2102 if (skippedSoFar == maxSize)
2103 return skippedSoFar;
2105 maxSize -= skippedSoFar;
2111 const qint64 bytesToSkip = qMin(size() - d->pos, maxSize);
2115 if (bytesToSkip > 0) {
2116 if (!seek(d->pos + bytesToSkip))
2117 return skippedSoFar ? skippedSoFar : Q_INT64_C(-1);
2118 if (bytesToSkip == maxSize)
2119 return skippedSoFar + bytesToSkip;
2121 skippedSoFar += bytesToSkip;
2122 maxSize -= bytesToSkip;
2126 const qint64 skipResult = skipData(maxSize);
2127 if (skippedSoFar == 0)
2130 if (skipResult == -1)
2131 return skippedSoFar;
2133 return skippedSoFar + skipResult;
2139qint64 QIODevicePrivate::skipByReading(qint64 maxSize)
2141 qint64 readSoFar = 0;
2144 const qint64 readBytes = qMin<qint64>(maxSize,
sizeof(dummy));
2145 const qint64 readResult = read(dummy, readBytes);
2148 if (readResult != readBytes) {
2152 if (readResult == -1)
2155 return readSoFar + readResult;
2158 readSoFar += readResult;
2159 maxSize -= readResult;
2160 }
while (maxSize > 0);
2179qint64 QIODevicePrivate::skipLine()
2182 qint64 readSoFar = 0;
2183 qint64 lastReadReturn = 0;
2185 while ((lastReadReturn = read(&c, 1)) == 1) {
2191#if defined QIODEVICE_DEBUG
2192 printf(
"%p QIODevicePrivate::skipLine(), pos = %lld, buffer.size() = %lld, "
2193 "returns %lld\n",
this, pos, buffer.size(), readSoFar);
2196 if (lastReadReturn != 1 && readSoFar == 0)
2197 return isSequential() ? lastReadReturn : -1;
2376 debug <<
"OpenMode(";
2377 QStringList modeList;
2378 if (modes == QIODevice::NotOpen) {
2379 modeList <<
"NotOpen"_L1;
2381 if (modes & QIODevice::ReadOnly)
2382 modeList <<
"ReadOnly"_L1;
2383 if (modes & QIODevice::WriteOnly)
2384 modeList <<
"WriteOnly"_L1;
2385 if (modes & QIODevice::Append)
2386 modeList <<
"Append"_L1;
2387 if (modes & QIODevice::Truncate)
2388 modeList <<
"Truncate"_L1;
2389 if (modes & QIODevice::Text)
2390 modeList <<
"Text"_L1;
2391 if (modes & QIODevice::Unbuffered)
2392 modeList <<
"Unbuffered"_L1;
2394 std::sort(modeList.begin(), modeList.end());
2395 debug << modeList.join(u'|');