617 |
617 |
618 \sa pos(), isSequential() |
618 \sa pos(), isSequential() |
619 */ |
619 */ |
620 bool QIODevice::seek(qint64 pos) |
620 bool QIODevice::seek(qint64 pos) |
621 { |
621 { |
622 if (d_func()->openMode == NotOpen) { |
622 Q_D(QIODevice); |
|
623 if (d->openMode == NotOpen) { |
623 qWarning("QIODevice::seek: The device is not open"); |
624 qWarning("QIODevice::seek: The device is not open"); |
624 return false; |
625 return false; |
625 } |
626 } |
626 if (pos < 0) { |
627 if (pos < 0) { |
627 qWarning("QIODevice::seek: Invalid pos: %d", int(pos)); |
628 qWarning("QIODevice::seek: Invalid pos: %d", int(pos)); |
628 return false; |
629 return false; |
629 } |
630 } |
630 |
631 |
631 Q_D(QIODevice); |
|
632 #if defined QIODEVICE_DEBUG |
632 #if defined QIODEVICE_DEBUG |
633 printf("%p QIODevice::seek(%d), before: d->pos = %d, d->buffer.size() = %d\n", |
633 printf("%p QIODevice::seek(%d), before: d->pos = %d, d->buffer.size() = %d\n", |
634 this, int(pos), int(d->pos), d->buffer.size()); |
634 this, int(pos), int(d->pos), d->buffer.size()); |
635 #endif |
635 #endif |
636 |
636 |
638 if (!d->isSequential()) { |
638 if (!d->isSequential()) { |
639 d->pos = pos; |
639 d->pos = pos; |
640 d->devicePos = pos; |
640 d->devicePos = pos; |
641 } |
641 } |
642 |
642 |
643 if (offset > 0 && !d->buffer.isEmpty()) { |
643 if (offset < 0 |
644 // When seeking forwards, we need to pop bytes off the front of the |
644 || offset >= qint64(d->buffer.size())) |
645 // buffer. |
|
646 do { |
|
647 int bytesToSkip = int(qMin<qint64>(offset, INT_MAX)); |
|
648 d->buffer.skip(bytesToSkip); |
|
649 offset -= bytesToSkip; |
|
650 } while (offset > 0); |
|
651 } else if (offset < 0) { |
|
652 // When seeking backwards, an operation that is only allowed for |
645 // When seeking backwards, an operation that is only allowed for |
653 // random-access devices, the buffer is cleared. The next read |
646 // random-access devices, the buffer is cleared. The next read |
654 // operation will then refill the buffer. We can optimize this, if we |
647 // operation will then refill the buffer. We can optimize this, if we |
655 // find that seeking backwards becomes a significant performance hit. |
648 // find that seeking backwards becomes a significant performance hit. |
656 d->buffer.clear(); |
649 d->buffer.clear(); |
657 } |
650 else if (!d->buffer.isEmpty()) |
|
651 d->buffer.skip(int(offset)); |
|
652 |
658 #if defined QIODEVICE_DEBUG |
653 #if defined QIODEVICE_DEBUG |
659 printf("%p \tafter: d->pos == %d, d->buffer.size() == %d\n", this, int(d->pos), |
654 printf("%p \tafter: d->pos == %d, d->buffer.size() == %d\n", this, int(d->pos), |
660 d->buffer.size()); |
655 d->buffer.size()); |
661 #endif |
656 #endif |
662 return true; |
657 return true; |
760 #endif |
755 #endif |
761 const bool sequential = d->isSequential(); |
756 const bool sequential = d->isSequential(); |
762 |
757 |
763 // Short circuit for getChar() |
758 // Short circuit for getChar() |
764 if (maxSize == 1) { |
759 if (maxSize == 1) { |
765 int chint = d->buffer.getChar(); |
760 int chint; |
766 if (chint != -1) { |
761 while ((chint = d->buffer.getChar()) != -1) { |
|
762 if (!sequential) |
|
763 ++d->pos; |
|
764 |
767 char c = char(uchar(chint)); |
765 char c = char(uchar(chint)); |
768 if (c == '\r' && (d->openMode & Text)) { |
766 if (c == '\r' && (d->openMode & Text)) |
769 d->buffer.ungetChar(c); |
767 continue; |
770 } else { |
768 *data = c; |
771 if (data) |
769 #if defined QIODEVICE_DEBUG |
772 *data = c; |
770 printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this, |
773 if (!sequential) |
771 int(c), isprint(c) ? c : '?'); |
774 ++d->pos; |
772 #endif |
775 #if defined QIODEVICE_DEBUG |
773 return qint64(1); |
776 printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this, |
|
777 int(c), isprint(c) ? c : '?'); |
|
778 #endif |
|
779 return qint64(1); |
|
780 } |
|
781 } |
774 } |
782 } |
775 } |
783 |
776 |
784 qint64 readSoFar = 0; |
777 qint64 readSoFar = 0; |
785 bool moreToRead = true; |
778 bool moreToRead = true; |
909 for reading, or that an error occurred. |
902 for reading, or that an error occurred. |
910 */ |
903 */ |
911 QByteArray QIODevice::read(qint64 maxSize) |
904 QByteArray QIODevice::read(qint64 maxSize) |
912 { |
905 { |
913 Q_D(QIODevice); |
906 Q_D(QIODevice); |
914 CHECK_MAXLEN(read, QByteArray()); |
907 QByteArray result; |
915 QByteArray tmp; |
908 |
916 qint64 readSoFar = 0; |
909 CHECK_MAXLEN(read, result); |
917 char buffer[4096]; |
910 |
918 #if defined QIODEVICE_DEBUG |
911 #if defined QIODEVICE_DEBUG |
919 printf("%p QIODevice::read(%d), d->pos = %d, d->buffer.size() = %d\n", |
912 printf("%p QIODevice::read(%d), d->pos = %d, d->buffer.size() = %d\n", |
920 this, int(maxSize), int(d->pos), int(d->buffer.size())); |
913 this, int(maxSize), int(d->pos), int(d->buffer.size())); |
921 #else |
914 #else |
922 Q_UNUSED(d); |
915 Q_UNUSED(d); |
923 #endif |
916 #endif |
924 |
917 |
925 do { |
918 if (maxSize != qint64(int(maxSize))) { |
926 qint64 bytesToRead = qMin(int(maxSize - readSoFar), int(sizeof(buffer))); |
919 qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit"); |
927 qint64 readBytes = read(buffer, bytesToRead); |
920 maxSize = INT_MAX; |
928 if (readBytes <= 0) |
921 } |
929 break; |
922 |
930 tmp.append(buffer, (int) readBytes); |
923 qint64 readBytes = 0; |
931 readSoFar += readBytes; |
924 if (maxSize) { |
932 } while (readSoFar < maxSize && bytesAvailable() > 0); |
925 result.resize(int(maxSize)); |
933 |
926 if (!result.size()) { |
934 return tmp; |
927 // If resize fails, read incrementally. |
|
928 qint64 readResult; |
|
929 do { |
|
930 result.resize(int(qMin(maxSize, result.size() + QIODEVICE_BUFFERSIZE))); |
|
931 readResult = read(result.data() + readBytes, result.size() - readBytes); |
|
932 if (readResult > 0 || readBytes == 0) |
|
933 readBytes += readResult; |
|
934 } while (readResult == QIODEVICE_BUFFERSIZE); |
|
935 } else { |
|
936 readBytes = read(result.data(), result.size()); |
|
937 } |
|
938 } |
|
939 |
|
940 if (readBytes <= 0) |
|
941 result.clear(); |
|
942 else |
|
943 result.resize(int(readBytes)); |
|
944 |
|
945 return result; |
935 } |
946 } |
936 |
947 |
937 /*! |
948 /*! |
938 \overload |
949 \overload |
939 |
950 |
950 #if defined QIODEVICE_DEBUG |
961 #if defined QIODEVICE_DEBUG |
951 printf("%p QIODevice::readAll(), d->pos = %d, d->buffer.size() = %d\n", |
962 printf("%p QIODevice::readAll(), d->pos = %d, d->buffer.size() = %d\n", |
952 this, int(d->pos), int(d->buffer.size())); |
963 this, int(d->pos), int(d->buffer.size())); |
953 #endif |
964 #endif |
954 |
965 |
955 QByteArray tmp; |
966 QByteArray result; |
956 if (d->isSequential() || size() == 0) { |
967 qint64 readBytes = 0; |
957 // Read it in chunks. Use bytesAvailable() as an unreliable hint for |
968 if (d->isSequential() || (readBytes = size()) == 0) { |
958 // sequential devices, but try to read 4K as a minimum. |
969 // Size is unknown, read incrementally. |
959 int chunkSize = qMax(qint64(4096), bytesAvailable()); |
970 qint64 readResult; |
960 qint64 totalRead = 0; |
971 do { |
961 forever { |
972 result.resize(result.size() + QIODEVICE_BUFFERSIZE); |
962 tmp.resize(tmp.size() + chunkSize); |
973 readResult = read(result.data() + readBytes, result.size() - readBytes); |
963 qint64 readBytes = read(tmp.data() + totalRead, chunkSize); |
974 if (readResult > 0 || readBytes == 0) |
964 tmp.chop(chunkSize - (readBytes < 0 ? 0 : readBytes)); |
975 readBytes += readResult; |
965 if (readBytes <= 0) |
976 } while (readResult > 0); |
966 return tmp; |
|
967 totalRead += readBytes; |
|
968 chunkSize = qMax(qint64(4096), bytesAvailable()); |
|
969 } |
|
970 } else { |
977 } else { |
971 // Read it all in one go. |
978 // Read it all in one go. |
972 tmp.resize(int(bytesAvailable())); |
979 // If resize fails, don't read anything. |
973 qint64 readBytes = read(tmp.data(), tmp.size()); |
980 result.resize(int(readBytes - d->pos)); |
974 tmp.resize(readBytes < 0 ? 0 : int(readBytes)); |
981 readBytes = read(result.data(), result.size()); |
975 } |
982 } |
976 return tmp; |
983 |
|
984 if (readBytes <= 0) |
|
985 result.clear(); |
|
986 else |
|
987 result.resize(int(readBytes)); |
|
988 |
|
989 return result; |
977 } |
990 } |
978 |
991 |
979 /*! |
992 /*! |
980 This function reads a line of ASCII characters from the device, up |
993 This function reads a line of ASCII characters from the device, up |
981 to a maximum of \a maxSize - 1 bytes, stores the characters in \a |
994 to a maximum of \a maxSize - 1 bytes, stores the characters in \a |
1120 for reading, or that an error occurred. |
1133 for reading, or that an error occurred. |
1121 */ |
1134 */ |
1122 QByteArray QIODevice::readLine(qint64 maxSize) |
1135 QByteArray QIODevice::readLine(qint64 maxSize) |
1123 { |
1136 { |
1124 Q_D(QIODevice); |
1137 Q_D(QIODevice); |
1125 CHECK_MAXLEN(readLine, QByteArray()); |
1138 QByteArray result; |
1126 QByteArray tmp; |
1139 |
1127 const int BufferGrowth = 4096; |
1140 CHECK_MAXLEN(readLine, result); |
1128 qint64 readSoFar = 0; |
|
1129 qint64 readBytes = 0; |
|
1130 |
1141 |
1131 #if defined QIODEVICE_DEBUG |
1142 #if defined QIODEVICE_DEBUG |
1132 printf("%p QIODevice::readLine(%d), d->pos = %d, d->buffer.size() = %d\n", |
1143 printf("%p QIODevice::readLine(%d), d->pos = %d, d->buffer.size() = %d\n", |
1133 this, int(maxSize), int(d->pos), int(d->buffer.size())); |
1144 this, int(maxSize), int(d->pos), int(d->buffer.size())); |
1134 #else |
1145 #else |
1135 Q_UNUSED(d); |
1146 Q_UNUSED(d); |
1136 #endif |
1147 #endif |
1137 |
1148 |
1138 do { |
1149 if (maxSize > INT_MAX) { |
1139 if (maxSize != 0) |
1150 qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit"); |
1140 tmp.resize(int(readSoFar + qMin(int(maxSize), BufferGrowth))); |
1151 maxSize = INT_MAX; |
1141 else |
1152 } |
1142 tmp.resize(int(readSoFar + BufferGrowth)); |
1153 |
1143 readBytes = readLine(tmp.data() + readSoFar, tmp.size() - readSoFar); |
1154 result.resize(int(maxSize)); |
1144 if (readBytes <= 0) |
1155 qint64 readBytes = 0; |
1145 break; |
1156 if (!result.size()) { |
1146 |
1157 // If resize fails or maxSize == 0, read incrementally |
1147 readSoFar += readBytes; |
1158 if (maxSize == 0) |
1148 } while ((!maxSize || readSoFar < maxSize) && |
1159 maxSize = INT_MAX; |
1149 readSoFar + 1 == tmp.size() && // +1 due to the ending null |
1160 |
1150 tmp.at(readSoFar - 1) != '\n'); |
1161 // The first iteration needs to leave an extra byte for the terminating null |
1151 |
1162 result.resize(1); |
1152 if (readSoFar == 0 && readBytes == -1) |
1163 |
1153 tmp.clear(); // return Null if we found an error |
1164 qint64 readResult; |
|
1165 do { |
|
1166 result.resize(int(qMin(maxSize, result.size() + QIODEVICE_BUFFERSIZE))); |
|
1167 readResult = readLine(result.data() + readBytes, result.size() - readBytes); |
|
1168 if (readResult > 0 || readBytes == 0) |
|
1169 readBytes += readResult; |
|
1170 } while (readResult == QIODEVICE_BUFFERSIZE |
|
1171 && result[int(readBytes - 1)] != '\n'); |
|
1172 } else |
|
1173 readBytes = readLine(result.data(), result.size()); |
|
1174 |
|
1175 if (readBytes <= 0) |
|
1176 result.clear(); |
1154 else |
1177 else |
1155 tmp.resize(int(readSoFar)); |
1178 result.resize(readBytes); |
1156 return tmp; |
1179 |
|
1180 return result; |
1157 } |
1181 } |
1158 |
1182 |
1159 /*! |
1183 /*! |
1160 Reads up to \a maxSize characters into \a data and returns the |
1184 Reads up to \a maxSize characters into \a data and returns the |
1161 number of characters read. |
1185 number of characters read. |
1383 \sa read() putChar() ungetChar() |
1407 \sa read() putChar() ungetChar() |
1384 */ |
1408 */ |
1385 bool QIODevice::getChar(char *c) |
1409 bool QIODevice::getChar(char *c) |
1386 { |
1410 { |
1387 Q_D(QIODevice); |
1411 Q_D(QIODevice); |
1388 const OpenMode openMode = d->openMode; |
1412 CHECK_READABLE(getChar, false); |
1389 if (!(openMode & ReadOnly)) { |
1413 |
1390 if (openMode == NotOpen) |
|
1391 qWarning("QIODevice::getChar: Closed device"); |
|
1392 else |
|
1393 qWarning("QIODevice::getChar: WriteOnly device"); |
|
1394 return false; |
|
1395 } |
|
1396 |
|
1397 // Shortcut for QIODevice::read(c, 1) |
|
1398 QRingBuffer *buffer = &d->buffer; |
|
1399 const int chint = buffer->getChar(); |
|
1400 if (chint != -1) { |
|
1401 char ch = char(uchar(chint)); |
|
1402 if ((openMode & Text) && ch == '\r') { |
|
1403 buffer->ungetChar(ch); |
|
1404 } else { |
|
1405 if (c) |
|
1406 *c = ch; |
|
1407 if (!d->isSequential()) |
|
1408 ++d->pos; |
|
1409 return true; |
|
1410 } |
|
1411 } |
|
1412 |
|
1413 // Fall back to read(). |
|
1414 char ch; |
1414 char ch; |
1415 if (read(&ch, 1) == 1) { |
1415 return (1 == read(c ? c : &ch, 1)); |
1416 if (c) |
|
1417 *c = ch; |
|
1418 return true; |
|
1419 } |
|
1420 return false; |
|
1421 } |
1416 } |
1422 |
1417 |
1423 /*! |
1418 /*! |
1424 \since 4.1 |
1419 \since 4.1 |
1425 |
1420 |