src/corelib/io/qiodevice.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   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