?? qtextstream.cpp
字號:
/*! \internal*/bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes){ // no buffer next to the QString itself; this function should only // be called internally, for devices. Q_ASSERT(!string); Q_ASSERT(device); // handle text translation and bypass the Text flag in the device. bool textModeEnabled = device->isTextModeEnabled(); if (textModeEnabled) device->setTextModeEnabled(false);#ifndef QT_NO_TEXTCODEC // codec auto detection, explicitly defaults to locale encoding if // the codec has been set to 0. if (!codec || autoDetectUnicode) { autoDetectUnicode = false; char bomBuffer[2]; if (device->peek(bomBuffer, 2) == 2 && (uchar(bomBuffer[0]) == 0xff && uchar(bomBuffer[1]) == 0xfe || uchar(bomBuffer[0]) == 0xfe && uchar(bomBuffer[1]) == 0xff)) { codec = QTextCodec::codecForName("UTF-16"); } else if (!codec) { codec = QTextCodec::codecForLocale(); writeConverterState.flags |= QTextCodec::IgnoreHeader; } }#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::fillReadBuffer(), using %s codec", codec->name().constData());#endif#endif // read raw data into a temporary buffer char buf[QTEXTSTREAM_BUFFERSIZE]; qint64 bytesRead = 0;#if defined(Q_OS_WIN) // On Windows, there is no non-blocking stdin - so we fall back to reading // lines instead. If there is no QOBJECT, we read lines for all sequential // devices; otherwise, we read lines only for stdin. QFile *file = 0; Q_UNUSED(file); if (device->isSequential()#if !defined(QT_NO_QOBJECT) && (file = qobject_cast<QFile *>(device)) && file->handle() == 0#endif ) { if (maxBytes != -1) bytesRead = device->readLine(buf, qMin<qint64>(sizeof(buf), maxBytes)); else bytesRead = device->readLine(buf, sizeof(buf)); } else#endif { if (maxBytes != -1) bytesRead = device->read(buf, qMin<qint64>(sizeof(buf), maxBytes)); else bytesRead = device->read(buf, sizeof(buf)); }#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::fillReadBuffer(), device->read(\"%s\", %d) == %d", qt_prettyDebug(buf, qMin(32,int(bytesRead)) , int(bytesRead)).constData(), sizeof(buf), int(bytesRead));#endif if (bytesRead <= 0) return false; int oldReadBufferSize = readBuffer.size(); readBuffer += endOfBufferState;#ifndef QT_NO_TEXTCODEC // convert to unicode readBuffer += codec->toUnicode(buf, bytesRead, &readConverterState);#else readBuffer += QString(QByteArray(buf, bytesRead));#endif // reset the Text flag. if (textModeEnabled) device->setTextModeEnabled(true); // remove all '\r\n' in the string. if (readBuffer.size() > oldReadBufferSize && textModeEnabled) { QChar CR = QLatin1Char('\r'); QChar LF = QLatin1Char('\n'); QChar *writePtr = readBuffer.data(); QChar *readPtr = readBuffer.data(); QChar *endPtr = readBuffer.data() + readBuffer.size(); int n = 0; while (readPtr < endPtr) { if (readPtr + 1 < endPtr && *readPtr == CR && *(readPtr + 1) == LF) { *writePtr = LF; if (n < readBufferOffset) --readBufferOffset; ++readPtr; } else if (readPtr != writePtr) { *writePtr = *readPtr; } ++n; ++writePtr; ++readPtr; } readBuffer.resize(writePtr - readBuffer.data()); if (readBuffer.endsWith(QLatin1Char('\r')) && !device->atEnd()) { endOfBufferState = QLatin1String("\r"); readBuffer.chop(1); } else { endOfBufferState.clear(); } }#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::fillReadBuffer() read %d bytes from device. readBuffer = [%s]", int(bytesRead), qt_prettyDebug(readBuffer.toLatin1(), readBuffer.size(), readBuffer.size()).data());#endif return true;}/*! \internal*/bool QTextStreamPrivate::flushWriteBuffer(){ // no buffer next to the QString itself; this function should only // be called internally, for devices. if (string || !device) return false; if (writeBuffer.isEmpty()) return true;#if defined (Q_OS_WIN) // handle text translation and bypass the Text flag in the device. bool textModeEnabled = device->isTextModeEnabled(); if (textModeEnabled) { device->setTextModeEnabled(false); writeBuffer.replace(QLatin1Char('\n'), QLatin1String("\r\n")); }#endif#ifndef QT_NO_TEXTCODEC if (!codec) codec = QTextCodec::codecForLocale();#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::flushWriteBuffer(), using %s codec (%s generating BOM)", codec->name().constData(), writeConverterState.flags & QTextCodec::IgnoreHeader ? "not" : "");#endif // convert from unicode to raw data QByteArray data = codec->fromUnicode(writeBuffer.data(), writeBuffer.size(), &writeConverterState);#else QByteArray data = writeBuffer.toLocal8Bit();#endif writeBuffer.clear(); // write raw data to the device qint64 bytesWritten = device->write(data);#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::flushWriteBuffer(), device->write(\"%s\") == %d", qt_prettyDebug(data.constData(), qMin(data.size(),32), data.size()).constData(), int(bytesWritten));#endif if (bytesWritten <= 0) return false;#if defined (Q_OS_WIN) // replace the text flag if (textModeEnabled) device->setTextModeEnabled(true);#endif // flush the file#ifndef QT_NO_QOBJECT QFile *file = qobject_cast<QFile *>(device); bool flushed = file && file->flush();#else bool flushed = true;#endif#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::flushWriteBuffer() wrote %d bytes", int(bytesWritten));#endif return flushed && bytesWritten == qint64(data.size());}/*! \internal Scans no more than \a maxlen QChars in the current buffer for the first \a delimiter. Stores a pointer to the start offset of the token in \a ptr, and the length in QChars in \a length.*/bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenDelimiter delimiter){ int totalSize = 0; int delimSize = 0; bool consumeDelimiter = false; bool foundToken = false; int startOffset = device ? readBufferOffset : stringOffset; QChar lastChar; bool canStillReadFromDevice = true; do { int endOffset; const QChar *chPtr; if (device) { chPtr = readBuffer.constData(); endOffset = readBuffer.size(); } else { chPtr = string->constData(); endOffset = string->size(); } chPtr += startOffset; for (; !foundToken && startOffset < endOffset && (!maxlen || totalSize < maxlen); ++startOffset) { const QChar ch = *chPtr++; ++totalSize; if (delimiter == Space && ch.isSpace()) { foundToken = true; delimSize = 1; } else if (delimiter == NotSpace && !ch.isSpace()) { foundToken = true; delimSize = 1; } else if (delimiter == EndOfLine && ch == QLatin1Char('\n')) { foundToken = true; delimSize = (lastChar == QLatin1Char('\r')) ? 2 : 1; consumeDelimiter = true; } lastChar = ch; } } while (!foundToken && (!maxlen || totalSize < maxlen) && (device && (canStillReadFromDevice = fillReadBuffer()))); // if the token was not found, but we reached the end of input, // then we accept what we got. if we are not at the end of input, // we return false. if (!foundToken && (!maxlen || totalSize < maxlen) && (totalSize == 0 || (string && stringOffset + totalSize < string->size()) || (device && !device->atEnd() && canStillReadFromDevice))) {#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::scan() did not find the token.");#endif return false; } // if we find a '\r' at the end of the data when reading lines, // don't make it part of the line. if (totalSize > 0 && !foundToken && delimiter == EndOfLine) { if (((string && stringOffset + totalSize == string->size()) || (device && device->atEnd())) && lastChar == QLatin1Char('\r')) { consumeDelimiter = true; ++delimSize; } } // set the read offset and length of the token if (length) *length = totalSize - delimSize; if (ptr) *ptr = readPtr(); // update last token size. the callee will call consumeLastToken() when // done. lastTokenSize = totalSize; if (!consumeDelimiter) lastTokenSize -= delimSize; qDebug("QTextStreamPrivate::scan(%p, %p, %d, %x) token length = %d, delimiter = %d", ptr, length, maxlen, (int)delimiter, totalSize - delimSize, delimSize);#endif return true;}/*! \internal*/inline const QChar *QTextStreamPrivate::readPtr() const{ Q_ASSERT(readBufferOffset <= readBuffer.size()); if (string) return string->constData() + stringOffset; return readBuffer.constData() + readBufferOffset;}/*! \internal*/inline void QTextStreamPrivate::consumeLastToken(){ if (lastTokenSize) consume(lastTokenSize); lastTokenSize = 0;}/*! \internal*/inline void QTextStreamPrivate::consume(int size){#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::consume(%d)", size);#endif if (string) { stringOffset += size; if (stringOffset > string->size()) stringOffset = string->size(); } else { readBufferOffset += size; if (readBufferOffset >= readBuffer.size()) { readBufferOffset = 0; readBuffer.clear(); readBufferStartDevicePos = device->pos();#ifndef QT_NO_TEXTCODEC copyConverterState(&readBufferStartReadConverterState, &readConverterState);#endif readBufferStartEndOfBufferState = endOfBufferState; } }}/*! \internal*/inline bool QTextStreamPrivate::write(const QString &data){ if (string) { // ### What about seek()?? string->append(data); } else { writeBuffer += data; if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE) return flushWriteBuffer(); } return true;}/*! \internal*/inline bool QTextStreamPrivate::getChar(QChar *ch){ if ((string && stringOffset == string->size()) || (device && readBuffer.isEmpty() && !fillReadBuffer())) { if (ch) *ch = 0; return false; } if (ch) *ch = *readPtr(); consume(1); return true;}/*! \internal*/inline void QTextStreamPrivate::ungetChar(const QChar &ch){ if (string) { if (stringOffset == 0) string->prepend(ch); else (*string)[--stringOffset] = ch; return; } if (readBufferOffset == 0) { readBuffer.prepend(ch); return; } readBuffer[--readBufferOffset] = ch;}/*! \internal*/inline bool QTextStreamPrivate::putString(const QString &s){ QString tmp = s; // handle padding int padSize = fieldWidth - s.size(); if (padSize > 0) { QString pad(padSize > 0 ? padSize : 0, padChar); if (fieldAlignment == QTextStream::AlignLeft) { tmp.append(QString(padSize, padChar)); } else if (fieldAlignment == QTextStream::AlignRight) { tmp.prepend(QString(padSize, padChar)); } else if (fieldAlignment == QTextStream::AlignCenter) { tmp.prepend(QString(padSize/2, padChar)); tmp.append(QString(padSize - padSize/2, padChar)); } }#if defined (QTEXTSTREAM_DEBUG) QByteArray a = s.toUtf8(); QByteArray b = tmp.toUtf8(); qDebug("QTextStreamPrivate::putString(\"%s\") calls write(\"%s\")", qt_prettyDebug(a.constData(), a.size(), qMax(16, a.size())).constData(), qt_prettyDebug(b.constData(), b.size(), qMax(16, b.size())).constData());#endif return write(tmp);}/*! Constructs a QTextStream. Before you can use it for reading or writing, you must assign a device or a string. \sa setDevice(), setString()*/QTextStream::QTextStream() : d_ptr(new QTextStreamPrivate(this)){#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStream::QTextStream()");#endif Q_D(QTextStream); d->status = Ok;}/*! Constructs a QTextStream that operates on \a device.*/QTextStream::QTextStream(QIODevice *device) : d_ptr(new QTextStreamPrivate(this)){#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStream::QTextStream(QIODevice *device == *%p)", device);#endif Q_D(QTextStream); d->device = device;#ifndef QT_NO_QOBJECT d->deviceClosedNotifier.setupDevice(this, d->device);#endif d->status = Ok;}/*! Constructs a QTextStream that operates on \a string, using \a openMode to define the open mode.*/QTextStream::QTextStream(QString *string, QIODevice::OpenMode openMode) : d_ptr(new QTextStreamPrivate(this)){#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStream::QTextStream(QString *string == *%p, openMode = %d)", string, int(openMode));#endif Q_D(QTextStream); d->string = string; d->stringOpenMode = openMode; d->status = Ok;}/*! Constructs a QTextStream that operates on \a array, using \a openMode to define the open mode. Internally, the array is wrapped by a QBuffer.*/QTextStream::QTextStream(QByteArray *array, QIODevice::OpenMode openMode) : d_ptr(new QTextStreamPrivate(this)){#if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStream::QTextStream(QByteArray *array == *%p, openMode = %d)", array, int(openMode));#endif Q_D(QTextStream); d->device = new QBuffer(array); d->device->open(openMode); d->deleteDevice = true;#ifndef QT_NO_QOBJECT
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -