diff options
author | David Faure <faure@kde.org> | 2012-02-26 10:05:39 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-03-06 12:09:57 +0100 |
commit | dc75c20397e7322ba87578e766e0cd86ece90f93 (patch) | |
tree | 1fd15d53a083f2386ae2608cd22a960af7d6c4d8 /src/corelib | |
parent | d51abed57a8f677a0d4eac57fd3f16bd4662190a (diff) |
Split up base class QFileDevice for open-file operations (read/write)
This will be used later on as a base class for QTemporaryFile and
QSaveFile.
Change-Id: Ic2e1d232f95dc29b8e2f75e24a881ab459d3f037
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/io/io.pri | 3 | ||||
-rw-r--r-- | src/corelib/io/qfile.cpp | 635 | ||||
-rw-r--r-- | src/corelib/io/qfile.h | 62 | ||||
-rw-r--r-- | src/corelib/io/qfile_p.h | 20 | ||||
-rw-r--r-- | src/corelib/io/qfiledevice.cpp | 736 | ||||
-rw-r--r-- | src/corelib/io/qfiledevice.h | 147 | ||||
-rw-r--r-- | src/corelib/io/qfiledevice_p.h | 104 |
7 files changed, 1012 insertions, 695 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 29599295ad..9c117abe03 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -11,6 +11,8 @@ HEADERS += \ io/qdir_p.h \ io/qdiriterator.h \ io/qfile.h \ + io/qfiledevice.h \ + io/qfiledevice_p.h \ io/qfileinfo.h \ io/qfileinfo_p.h \ io/qiodevice.h \ @@ -49,6 +51,7 @@ SOURCES += \ io/qdir.cpp \ io/qdiriterator.cpp \ io/qfile.cpp \ + io/qfiledevice.cpp \ io/qfileinfo.cpp \ io/qiodevice.cpp \ io/qnoncontiguousbytedevice.cpp \ diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 6640dca70b..433d4493e5 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE -static const int QFILE_WRITEBUFFER_SIZE = 16384; - static QByteArray locale_encode(const QString &f) { #if defined(Q_OS_DARWIN) @@ -86,16 +84,11 @@ QFile::EncoderFn QFilePrivate::encoder = locale_encode; QFile::DecoderFn QFilePrivate::decoder = locale_decode; QFilePrivate::QFilePrivate() - : fileEngine(0), lastWasWrite(false), - writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError), - cachedSize(0) { } QFilePrivate::~QFilePrivate() { - delete fileEngine; - fileEngine = 0; } bool @@ -137,39 +130,6 @@ QAbstractFileEngine *QFilePrivate::engine() const return fileEngine; } -inline bool QFilePrivate::ensureFlushed() const -{ - // This function ensures that the write buffer has been flushed (const - // because certain const functions need to call it. - if (lastWasWrite) { - const_cast<QFilePrivate *>(this)->lastWasWrite = false; - if (!const_cast<QFile *>(q_func())->flush()) - return false; - } - return true; -} - -void -QFilePrivate::setError(QFile::FileError err) -{ - error = err; - errorString.clear(); -} - -void -QFilePrivate::setError(QFile::FileError err, const QString &errStr) -{ - error = err; - errorString = errStr; -} - -void -QFilePrivate::setError(QFile::FileError err, int errNum) -{ - error = err; - errorString = qt_error_string(errNum); -} - //************* QFile /*! @@ -278,98 +238,18 @@ QFilePrivate::setError(QFile::FileError err, int errNum) \sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System} */ -/*! - \enum QFile::FileError - - This enum describes the errors that may be returned by the error() - function. - - \value NoError No error occurred. - \value ReadError An error occurred when reading from the file. - \value WriteError An error occurred when writing to the file. - \value FatalError A fatal error occurred. - \value ResourceError - \value OpenError The file could not be opened. - \value AbortError The operation was aborted. - \value TimeOutError A timeout occurred. - \value UnspecifiedError An unspecified error occurred. - \value RemoveError The file could not be removed. - \value RenameError The file could not be renamed. - \value PositionError The position in the file could not be changed. - \value ResizeError The file could not be resized. - \value PermissionsError The file could not be accessed. - \value CopyError The file could not be copied. - - \omitvalue ConnectError -*/ - -/*! - \enum QFile::Permission - - This enum is used by the permission() function to report the - permissions and ownership of a file. The values may be OR-ed - together to test multiple permissions and ownership values. - - \value ReadOwner The file is readable by the owner of the file. - \value WriteOwner The file is writable by the owner of the file. - \value ExeOwner The file is executable by the owner of the file. - \value ReadUser The file is readable by the user. - \value WriteUser The file is writable by the user. - \value ExeUser The file is executable by the user. - \value ReadGroup The file is readable by the group. - \value WriteGroup The file is writable by the group. - \value ExeGroup The file is executable by the group. - \value ReadOther The file is readable by anyone. - \value WriteOther The file is writable by anyone. - \value ExeOther The file is executable by anyone. - - \warning Because of differences in the platforms supported by Qt, - the semantics of ReadUser, WriteUser and ExeUser are - platform-dependent: On Unix, the rights of the owner of the file - are returned and on Windows the rights of the current user are - returned. This behavior might change in a future Qt version. - - Note that Qt does not by default check for permissions on NTFS - file systems, as this may decrease the performance of file - handling considerably. It is possible to force permission checking - on NTFS by including the following code in your source: - - \snippet doc/src/snippets/ntfsp.cpp 0 - - Permission checking is then turned on and off by incrementing and - decrementing \c qt_ntfs_permission_lookup by 1. - - \snippet doc/src/snippets/ntfsp.cpp 1 -*/ - -/*! - \enum QFile::FileHandleFlag - - This enum is used when opening a file to specify additional - options which only apply to files and not to a generic - QIODevice. - - \value AutoCloseHandle The file handle passed into open() should be - closed by close(), the default behavior is that close just flushes - the file and the application is responsible for closing the file handle. - When opening a file by name, this flag is ignored as Qt always owns the - file handle and must close it. - \value DontCloseHandle If not explicitly closed, the underlying file - handle is left open when the QFile object is destroyed. - */ - #ifdef QT_NO_QOBJECT QFile::QFile() - : QIODevice(*new QFilePrivate) + : QFileDevice(*new QFilePrivate) { } QFile::QFile(const QString &name) - : QIODevice(*new QFilePrivate) + : QFileDevice(*new QFilePrivate) { d_func()->fileName = name; } QFile::QFile(QFilePrivate &dd) - : QIODevice(dd) + : QFileDevice(dd) { } #else @@ -377,21 +257,21 @@ QFile::QFile(QFilePrivate &dd) \internal */ QFile::QFile() - : QIODevice(*new QFilePrivate, 0) + : QFileDevice(*new QFilePrivate, 0) { } /*! Constructs a new file object with the given \a parent. */ QFile::QFile(QObject *parent) - : QIODevice(*new QFilePrivate, parent) + : QFileDevice(*new QFilePrivate, parent) { } /*! Constructs a new file object to represent the file with the given \a name. */ QFile::QFile(const QString &name) - : QIODevice(*new QFilePrivate, 0) + : QFileDevice(*new QFilePrivate, 0) { Q_D(QFile); d->fileName = name; @@ -401,7 +281,7 @@ QFile::QFile(const QString &name) file with the specified \a name. */ QFile::QFile(const QString &name, QObject *parent) - : QIODevice(*new QFilePrivate, parent) + : QFileDevice(*new QFilePrivate, parent) { Q_D(QFile); d->fileName = name; @@ -410,7 +290,7 @@ QFile::QFile(const QString &name, QObject *parent) \internal */ QFile::QFile(QFilePrivate &dd, QObject *parent) - : QIODevice(dd, parent) + : QFileDevice(dd, parent) { } #endif @@ -420,7 +300,6 @@ QFile::QFile(QFilePrivate &dd, QObject *parent) */ QFile::~QFile() { - close(); } /*! @@ -962,20 +841,6 @@ QFile::copy(const QString &fileName, const QString &newName) } /*! - Returns true if the file can only be manipulated sequentially; - otherwise returns false. - - Most files support random-access, but some special files may not. - - \sa QIODevice::isSequential() -*/ -bool QFile::isSequential() const -{ - Q_D(const QFile); - return d->fileEngine && d->fileEngine->isSequential(); -} - -/*! Opens the file using OpenMode \a mode, returning true if successful; otherwise false. @@ -1149,119 +1014,11 @@ bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags) } /*! - Returns the file handle of the file. - - This is a small positive integer, suitable for use with C library - functions such as fdopen() and fcntl(). On systems that use file - descriptors for sockets (i.e. Unix systems, but not Windows) the handle - can be used with QSocketNotifier as well. - - If the file is not open, or there is an error, handle() returns -1. - - This function is not supported on Windows CE. - - \sa QSocketNotifier -*/ - -int -QFile::handle() const -{ - Q_D(const QFile); - if (!isOpen() || !d->fileEngine) - return -1; - - return d->fileEngine->handle(); -} - -/*! - \enum QFile::MemoryMapFlags - \since 4.4 - - This enum describes special options that may be used by the map() - function. - - \value NoOptions No options. -*/ - -/*! - \since 4.4 - Maps \a size bytes of the file into memory starting at \a offset. A file - should be open for a map to succeed but the file does not need to stay - open after the memory has been mapped. When the QFile is destroyed - or a new file is opened with this object, any maps that have not been - unmapped will automatically be unmapped. - - Any mapping options can be passed through \a flags. - - Returns a pointer to the memory or 0 if there is an error. - - \note On Windows CE 5.0 the file will be closed before mapping occurs. - - \sa unmap() - */ -uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags) -{ - Q_D(QFile); - if (d->engine() - && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) { - unsetError(); - uchar *address = d->fileEngine->map(offset, size, flags); - if (address == 0) - d->setError(d->fileEngine->error(), d->fileEngine->errorString()); - return address; - } - return 0; -} - -/*! - \since 4.4 - Unmaps the memory \a address. - - Returns true if the unmap succeeds; false otherwise. - - \sa map() - */ -bool QFile::unmap(uchar *address) -{ - Q_D(QFile); - if (d->engine() - && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) { - unsetError(); - bool success = d->fileEngine->unmap(address); - if (!success) - d->setError(d->fileEngine->error(), d->fileEngine->errorString()); - return success; - } - d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension")); - return false; -} - -/*! - Sets the file size (in bytes) \a sz. Returns true if the file if the - resize succeeds; false otherwise. If \a sz is larger than the file - currently is the new bytes will be set to 0, if \a sz is smaller the - file is simply truncated. - - \sa size(), setFileName() + \reimp */ - -bool -QFile::resize(qint64 sz) +bool QFile::resize(qint64 sz) { - Q_D(QFile); - if (!d->ensureFlushed()) - return false; - d->engine(); - if (isOpen() && d->fileEngine->pos() > sz) - seek(sz); - if(d->fileEngine->setSize(sz)) { - unsetError(); - d->cachedSize = sz; - return true; - } - d->cachedSize = 0; - d->setError(QFile::ResizeError, d->fileEngine->errorString()); - return false; + return QFileDevice::resize(sz); // for now } /*! @@ -1282,18 +1039,11 @@ QFile::resize(const QString &fileName, qint64 sz) } /*! - Returns the complete OR-ed together combination of - QFile::Permission for the file. - - \sa setPermissions(), setFileName() + \reimp */ - -QFile::Permissions -QFile::permissions() const +QFile::Permissions QFile::permissions() const { - Q_D(const QFile); - QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask; - return QFile::Permissions((int)perms); //ewww + return QFileDevice::permissions(); // for now } /*! @@ -1317,16 +1067,9 @@ QFile::permissions(const QString &fileName) \sa permissions(), setFileName() */ -bool -QFile::setPermissions(Permissions permissions) +bool QFile::setPermissions(Permissions permissions) { - Q_D(QFile); - if (d->engine()->setPermissions(permissions)) { - unsetError(); - return true; - } - d->setError(QFile::PermissionsError, d->fileEngine->errorString()); - return false; + return QFileDevice::setPermissions(permissions); // for now } /*! @@ -1341,354 +1084,12 @@ QFile::setPermissions(const QString &fileName, Permissions permissions) return QFile(fileName).setPermissions(permissions); } -static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer) -{ - qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize()); - if (ret > 0) - buffer->free(ret); - return ret; -} - -/*! - Flushes any buffered data to the file. Returns true if successful; - otherwise returns false. -*/ - -bool -QFile::flush() -{ - Q_D(QFile); - if (!d->fileEngine) { - qWarning("QFile::flush: No file engine. Is IODevice open?"); - return false; - } - - if (!d->writeBuffer.isEmpty()) { - qint64 size = d->writeBuffer.size(); - if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::WriteError; - d->setError(err, d->fileEngine->errorString()); - return false; - } - } - - if (!d->fileEngine->flush()) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::WriteError; - d->setError(err, d->fileEngine->errorString()); - return false; - } - return true; -} - -/*! - Calls QFile::flush() and closes the file. Errors from flush are ignored. - - \sa QIODevice::close() -*/ -void -QFile::close() -{ - Q_D(QFile); - if(!isOpen()) - return; - bool flushed = flush(); - QIODevice::close(); - - // reset write buffer - d->lastWasWrite = false; - d->writeBuffer.clear(); - - // keep earlier error from flush - if (d->fileEngine->close() && flushed) - unsetError(); - else if (flushed) - d->setError(d->fileEngine->error(), d->fileEngine->errorString()); -} - -/*! - Returns the size of the file. - - For regular empty files on Unix (e.g. those in \c /proc), this function - returns 0; the contents of such a file are generated on demand in response - to you calling read(). -*/ - -qint64 QFile::size() const -{ - Q_D(const QFile); - if (!d->ensureFlushed()) - return 0; - d->cachedSize = d->engine()->size(); - return d->cachedSize; -} - -/*! - \reimp -*/ - -qint64 QFile::pos() const -{ - return QIODevice::pos(); -} - -/*! - Returns true if the end of the file has been reached; otherwise returns - false. - - For regular empty files on Unix (e.g. those in \c /proc), this function - returns true, since the file system reports that the size of such a file is - 0. Therefore, you should not depend on atEnd() when reading data from such a - file, but rather call read() until no more data can be read. -*/ - -bool QFile::atEnd() const -{ - Q_D(const QFile); - - // If there's buffered data left, we're not at the end. - if (!d->buffer.isEmpty()) - return false; - - if (!isOpen()) - return true; - - if (!d->ensureFlushed()) - return false; - - // If the file engine knows best, say what it says. - if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) { - // Check if the file engine supports AtEndExtension, and if it does, - // check if the file engine claims to be at the end. - return d->fileEngine->atEnd(); - } - - // if it looks like we are at the end, or if size is not cached, - // fall through to bytesAvailable() to make sure. - if (pos() < d->cachedSize) - return false; - - // Fall back to checking how much is available (will stat files). - return bytesAvailable() == 0; -} - -/*! - \fn bool QFile::seek(qint64 pos) - - For random-access devices, this function sets the current position - to \a pos, returning true on success, or false if an error occurred. - For sequential devices, the default behavior is to do nothing and - return false. - - Seeking beyond the end of a file: - If the position is beyond the end of a file, then seek() shall not - immediately extend the file. If a write is performed at this position, - then the file shall be extended. The content of the file between the - previous end of file and the newly written data is UNDEFINED and - varies between platforms and file systems. -*/ - -bool QFile::seek(qint64 off) -{ - Q_D(QFile); - if (!isOpen()) { - qWarning("QFile::seek: IODevice is not open"); - return false; - } - - if (!d->ensureFlushed()) - return false; - - if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::PositionError; - d->setError(err, d->fileEngine->errorString()); - return false; - } - unsetError(); - return true; -} - -/*! - \reimp -*/ -qint64 QFile::readLineData(char *data, qint64 maxlen) -{ - Q_D(QFile); - if (!d->ensureFlushed()) - return -1; - - qint64 read; - if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) { - read = d->fileEngine->readLine(data, maxlen); - } else { - // Fall back to QIODevice's readLine implementation if the engine - // cannot do it faster. - read = QIODevice::readLineData(data, maxlen); - } - - if (read < maxlen) { - // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked - d->cachedSize = 0; - } - - return read; -} - -/*! - \reimp -*/ - -qint64 QFile::readData(char *data, qint64 len) -{ - Q_D(QFile); - unsetError(); - if (!d->ensureFlushed()) - return -1; - - qint64 read = d->fileEngine->read(data, len); - if(read < 0) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::ReadError; - d->setError(err, d->fileEngine->errorString()); - } - - if (read < len) { - // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked - d->cachedSize = 0; - } - - return read; -} - -/*! - \internal -*/ -bool QFilePrivate::putCharHelper(char c) -{ -#ifdef QT_NO_QOBJECT - return QIODevicePrivate::putCharHelper(c); -#else - - // Cutoff for code that doesn't only touch the buffer. - int writeBufferSize = writeBuffer.size(); - if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE -#ifdef Q_OS_WIN - || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE) -#endif - ) { - return QIODevicePrivate::putCharHelper(c); - } - - if (!(openMode & QIODevice::WriteOnly)) { - if (openMode == QIODevice::NotOpen) - qWarning("QIODevice::putChar: Closed device"); - else - qWarning("QIODevice::putChar: ReadOnly device"); - return false; - } - - // Make sure the device is positioned correctly. - const bool sequential = isSequential(); - if (pos != devicePos && !sequential && !q_func()->seek(pos)) - return false; - - lastWasWrite = true; - - int len = 1; -#ifdef Q_OS_WIN - if ((openMode & QIODevice::Text) && c == '\n') { - ++len; - *writeBuffer.reserve(1) = '\r'; - } -#endif - - // Write to buffer. - *writeBuffer.reserve(1) = c; - - if (!sequential) { - pos += len; - devicePos += len; - if (!buffer.isEmpty()) - buffer.skip(len); - } - - return true; -#endif -} - /*! \reimp */ - -qint64 -QFile::writeData(const char *data, qint64 len) -{ - Q_D(QFile); - unsetError(); - d->lastWasWrite = true; - bool buffered = !(d->openMode & Unbuffered); - - // Flush buffered data if this read will overflow. - if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) { - if (!flush()) - return -1; - } - - // Write directly to the engine if the block size is larger than - // the write buffer size. - if (!buffered || len > QFILE_WRITEBUFFER_SIZE) { - qint64 ret = d->fileEngine->write(data, len); - if(ret < 0) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::WriteError; - d->setError(err, d->fileEngine->errorString()); - } - return ret; - } - - // Write to the buffer. - char *writePointer = d->writeBuffer.reserve(len); - if (len == 1) - *writePointer = *data; - else - ::memcpy(writePointer, data, len); - return len; -} - -/*! - Returns the file error status. - - The I/O device status returns an error code. For example, if open() - returns false, or a read/write operation returns -1, this function can - be called to find out the reason why the operation failed. - - \sa unsetError() -*/ - -QFile::FileError -QFile::error() const -{ - Q_D(const QFile); - return d->error; -} - -/*! - Sets the file's error to QFile::NoError. - - \sa error() -*/ -void -QFile::unsetError() +qint64 QFile::size() const { - Q_D(QFile); - d->setError(QFile::NoError); + return QFileDevice::size(); // for now } QT_END_NAMESPACE diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h index 7f370d4214..0ee8f39d95 100644 --- a/src/corelib/io/qfile.h +++ b/src/corelib/io/qfile.h @@ -42,7 +42,7 @@ #ifndef QFILE_H #define QFILE_H -#include <QtCore/qiodevice.h> +#include <QtCore/qfiledevice.h> #include <QtCore/qstring.h> #include <stdio.h> @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE class QTemporaryFile; class QFilePrivate; -class Q_CORE_EXPORT QFile : public QIODevice +class Q_CORE_EXPORT QFile : public QFileDevice { #ifndef QT_NO_QOBJECT Q_OBJECT @@ -65,39 +65,6 @@ class Q_CORE_EXPORT QFile : public QIODevice Q_DECLARE_PRIVATE(QFile) public: - - enum FileError { - NoError = 0, - ReadError = 1, - WriteError = 2, - FatalError = 3, - ResourceError = 4, - OpenError = 5, - AbortError = 6, - TimeOutError = 7, - UnspecifiedError = 8, - RemoveError = 9, - RenameError = 10, - PositionError = 11, - ResizeError = 12, - PermissionsError = 13, - CopyError = 14 - }; - - enum Permission { - ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000, - ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100, - ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010, - ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001 - }; - Q_DECLARE_FLAGS(Permissions, Permission) - - enum FileHandleFlag { - AutoCloseHandle = 0x0001, - DontCloseHandle = 0 - }; - Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag) - QFile(); QFile(const QString &name); #ifndef QT_NO_QOBJECT @@ -106,9 +73,6 @@ public: #endif ~QFile(); - FileError error() const; - void unsetError(); - QString fileName() const; void setFileName(const QString &name); @@ -141,18 +105,11 @@ public: bool copy(const QString &newName); static bool copy(const QString &fileName, const QString &newName); - bool isSequential() const; - bool open(OpenMode flags); bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); - virtual void close(); qint64 size() const; - qint64 pos() const; - bool seek(qint64 offset); - bool atEnd() const; - bool flush(); bool resize(qint64 sz); static bool resize(const QString &filename, qint64 sz); @@ -162,15 +119,6 @@ public: bool setPermissions(Permissions permissionSpec); static bool setPermissions(const QString &filename, Permissions permissionSpec); - int handle() const; - - enum MemoryMapFlags { - NoOptions = 0 - }; - - uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions); - bool unmap(uchar *address); - protected: #ifdef QT_NO_QOBJECT QFile(QFilePrivate &dd); @@ -178,17 +126,11 @@ protected: QFile(QFilePrivate &dd, QObject *parent = 0); #endif - qint64 readData(char *data, qint64 maxlen); - qint64 writeData(const char *data, qint64 len); - qint64 readLineData(char *data, qint64 maxlen); - private: friend class QTemporaryFile; Q_DISABLE_COPY(QFile) }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QFile::Permissions) - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h index 3d2d3d678b..575d7d14b9 100644 --- a/src/corelib/io/qfile_p.h +++ b/src/corelib/io/qfile_p.h @@ -53,15 +53,13 @@ // We mean it. // -#include "private/qabstractfileengine_p.h" -#include "private/qiodevice_p.h" -#include "private/qringbuffer_p.h" +#include "private/qfiledevice_p.h" QT_BEGIN_NAMESPACE class QTemporaryFile; -class QFilePrivate : public QIODevicePrivate +class QFilePrivate : public QFileDevicePrivate { Q_DECLARE_PUBLIC(QFile) friend class QTemporaryFile; @@ -76,20 +74,6 @@ protected: virtual QAbstractFileEngine *engine() const; QString fileName; - mutable QAbstractFileEngine *fileEngine; - - bool lastWasWrite; - QRingBuffer writeBuffer; - inline bool ensureFlushed() const; - - bool putCharHelper(char c); - - QFile::FileError error; - void setError(QFile::FileError err); - void setError(QFile::FileError err, const QString &errorString); - void setError(QFile::FileError err, int errNum); - - mutable qint64 cachedSize; private: static QFile::EncoderFn encoder; diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp new file mode 100644 index 0000000000..17eedb0bdd --- /dev/null +++ b/src/corelib/io/qfiledevice.cpp @@ -0,0 +1,736 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" +#include "qfiledevice.h" +#include "qfiledevice_p.h" +#include "qfsfileengine_p.h" + +#ifdef QT_NO_QOBJECT +#define tr(X) QString::fromLatin1(X) +#endif + +QT_BEGIN_NAMESPACE + +static const int QFILE_WRITEBUFFER_SIZE = 16384; + +QFileDevicePrivate::QFileDevicePrivate() + : fileEngine(0), lastWasWrite(false), + writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError), + cachedSize(0) +{ +} + +QFileDevicePrivate::~QFileDevicePrivate() +{ + delete fileEngine; + fileEngine = 0; +} + +QAbstractFileEngine * QFileDevicePrivate::engine() const +{ + if (!fileEngine) + fileEngine = new QFSFileEngine; + return fileEngine; +} + +void QFileDevicePrivate::setError(QFileDevice::FileError err) +{ + error = err; + errorString.clear(); +} + +void QFileDevicePrivate::setError(QFileDevice::FileError err, const QString &errStr) +{ + error = err; + errorString = errStr; +} + +void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum) +{ + error = err; + errorString = qt_error_string(errNum); +} + +/*! + \enum QFileDevice::FileError + + This enum describes the errors that may be returned by the error() + function. + + \value NoError No error occurred. + \value ReadError An error occurred when reading from the file. + \value WriteError An error occurred when writing to the file. + \value FatalError A fatal error occurred. + \value ResourceError + \value OpenError The file could not be opened. + \value AbortError The operation was aborted. + \value TimeOutError A timeout occurred. + \value UnspecifiedError An unspecified error occurred. + \value RemoveError The file could not be removed. + \value RenameError The file could not be renamed. + \value PositionError The position in the file could not be changed. + \value ResizeError The file could not be resized. + \value PermissionsError The file could not be accessed. + \value CopyError The file could not be copied. + + \omitvalue ConnectError +*/ + +/*! + \enum QFileDevice::Permission + + This enum is used by the permission() function to report the + permissions and ownership of a file. The values may be OR-ed + together to test multiple permissions and ownership values. + + \value ReadOwner The file is readable by the owner of the file. + \value WriteOwner The file is writable by the owner of the file. + \value ExeOwner The file is executable by the owner of the file. + \value ReadUser The file is readable by the user. + \value WriteUser The file is writable by the user. + \value ExeUser The file is executable by the user. + \value ReadGroup The file is readable by the group. + \value WriteGroup The file is writable by the group. + \value ExeGroup The file is executable by the group. + \value ReadOther The file is readable by anyone. + \value WriteOther The file is writable by anyone. + \value ExeOther The file is executable by anyone. + + \warning Because of differences in the platforms supported by Qt, + the semantics of ReadUser, WriteUser and ExeUser are + platform-dependent: On Unix, the rights of the owner of the file + are returned and on Windows the rights of the current user are + returned. This behavior might change in a future Qt version. + + Note that Qt does not by default check for permissions on NTFS + file systems, as this may decrease the performance of file + handling considerably. It is possible to force permission checking + on NTFS by including the following code in your source: + + \snippet doc/src/snippets/ntfsp.cpp 0 + + Permission checking is then turned on and off by incrementing and + decrementing \c qt_ntfs_permission_lookup by 1. + + \snippet doc/src/snippets/ntfsp.cpp 1 +*/ + +//************* QFileDevice + +/*! + \class QFileDevice + \since 5.0 + + \brief The QFileDevice class provides an interface for reading from and writing to open files. + + \ingroup io + + \reentrant + + QFileDevice is the base class for I/O devices that can read and write text and binary files + and \l{The Qt Resource System}{resources}. QFile offers the main functionality, + QFileDevice serves as a base class for sharing functionality with other file devices such + as QTemporaryFile, by providing all the operations that can be done on files that have + been opened by QFile or QTemporaryFile. + + \sa QFile, QTemporaryFile +*/ + +/*! + \enum QFileDevice::FileHandleFlag + + This enum is used when opening a file to specify additional + options which only apply to files and not to a generic + QIODevice. + + \value AutoCloseHandle The file handle passed into open() should be + closed by close(), the default behavior is that close just flushes + the file and the application is responsible for closing the file handle. + When opening a file by name, this flag is ignored as Qt always owns the + file handle and must close it. + \value DontCloseHandle If not explicitly closed, the underlying file + handle is left open when the QFile object is destroyed. + */ + +#ifdef QT_NO_QOBJECT +QFileDevice::QFileDevice() + : QIODevice(*new QFileDevicePrivate) +{ +} +QFileDevice::QFileDevice(QFileDevicePrivate &dd) + : QIODevice(dd) +{ +} +#else +/*! + \internal +*/ +QFileDevice::QFileDevice() + : QIODevice(*new QFileDevicePrivate, 0) +{ +} +/*! + \internal +*/ +QFileDevice::QFileDevice(QObject *parent) + : QIODevice(*new QFileDevicePrivate, parent) +{ +} +/*! + \internal +*/ +QFileDevice::QFileDevice(QFileDevicePrivate &dd, QObject *parent) + : QIODevice(dd, parent) +{ +} +#endif + +/*! + Destroys the file device, closing it if necessary. +*/ +QFileDevice::~QFileDevice() +{ + close(); +} + +/*! + Returns true if the file can only be manipulated sequentially; + otherwise returns false. + + Most files support random-access, but some special files may not. + + \sa QIODevice::isSequential() +*/ +bool QFileDevice::isSequential() const +{ + Q_D(const QFileDevice); + return d->fileEngine && d->fileEngine->isSequential(); +} + +/*! + Returns the file handle of the file. + + This is a small positive integer, suitable for use with C library + functions such as fdopen() and fcntl(). On systems that use file + descriptors for sockets (i.e. Unix systems, but not Windows) the handle + can be used with QSocketNotifier as well. + + If the file is not open, or there is an error, handle() returns -1. + + This function is not supported on Windows CE. + + \sa QSocketNotifier +*/ +int QFileDevice::handle() const +{ + Q_D(const QFileDevice); + if (!isOpen() || !d->fileEngine) + return -1; + + return d->fileEngine->handle(); +} + +/*! + Returns the name of the file. + The default implementation in QFileDevice returns QString(). +*/ +QString QFileDevice::fileName() const +{ + return QString(); +} + +static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer) +{ + qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize()); + if (ret > 0) + buffer->free(ret); + return ret; +} + +/*! + Flushes any buffered data to the file. Returns true if successful; + otherwise returns false. +*/ +bool QFileDevice::flush() +{ + Q_D(QFileDevice); + if (!d->fileEngine) { + qWarning("QFileDevice::flush: No file engine. Is IODevice open?"); + return false; + } + + if (!d->writeBuffer.isEmpty()) { + qint64 size = d->writeBuffer.size(); + if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::WriteError; + d->setError(err, d->fileEngine->errorString()); + return false; + } + } + + if (!d->fileEngine->flush()) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::WriteError; + d->setError(err, d->fileEngine->errorString()); + return false; + } + return true; +} + +/*! + Calls QFileDevice::flush() and closes the file. Errors from flush are ignored. + + \sa QIODevice::close() +*/ +void QFileDevice::close() +{ + Q_D(QFileDevice); + if (!isOpen()) + return; + bool flushed = flush(); + QIODevice::close(); + + // reset write buffer + d->lastWasWrite = false; + d->writeBuffer.clear(); + + // keep earlier error from flush + if (d->fileEngine->close() && flushed) + unsetError(); + else if (flushed) + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); +} + +/*! + \reimp +*/ +qint64 QFileDevice::pos() const +{ + return QIODevice::pos(); +} + +/*! + Returns true if the end of the file has been reached; otherwise returns + false. + + For regular empty files on Unix (e.g. those in \c /proc), this function + returns true, since the file system reports that the size of such a file is + 0. Therefore, you should not depend on atEnd() when reading data from such a + file, but rather call read() until no more data can be read. +*/ +bool QFileDevice::atEnd() const +{ + Q_D(const QFileDevice); + + // If there's buffered data left, we're not at the end. + if (!d->buffer.isEmpty()) + return false; + + if (!isOpen()) + return true; + + if (!d->ensureFlushed()) + return false; + + // If the file engine knows best, say what it says. + if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) { + // Check if the file engine supports AtEndExtension, and if it does, + // check if the file engine claims to be at the end. + return d->fileEngine->atEnd(); + } + + // if it looks like we are at the end, or if size is not cached, + // fall through to bytesAvailable() to make sure. + if (pos() < d->cachedSize) + return false; + + // Fall back to checking how much is available (will stat files). + return bytesAvailable() == 0; +} + +/*! + \fn bool QFileDevice::seek(qint64 pos) + + For random-access devices, this function sets the current position + to \a pos, returning true on success, or false if an error occurred. + For sequential devices, the default behavior is to do nothing and + return false. + + Seeking beyond the end of a file: + If the position is beyond the end of a file, then seek() shall not + immediately extend the file. If a write is performed at this position, + then the file shall be extended. The content of the file between the + previous end of file and the newly written data is UNDEFINED and + varies between platforms and file systems. +*/ +bool QFileDevice::seek(qint64 off) +{ + Q_D(QFileDevice); + if (!isOpen()) { + qWarning("QFileDevice::seek: IODevice is not open"); + return false; + } + + if (!d->ensureFlushed()) + return false; + + if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::PositionError; + d->setError(err, d->fileEngine->errorString()); + return false; + } + unsetError(); + return true; +} + +/*! + \reimp +*/ +qint64 QFileDevice::readLineData(char *data, qint64 maxlen) +{ + Q_D(QFileDevice); + if (!d->ensureFlushed()) + return -1; + + qint64 read; + if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) { + read = d->fileEngine->readLine(data, maxlen); + } else { + // Fall back to QIODevice's readLine implementation if the engine + // cannot do it faster. + read = QIODevice::readLineData(data, maxlen); + } + + if (read < maxlen) { + // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked + d->cachedSize = 0; + } + + return read; +} + +/*! + \reimp +*/ +qint64 QFileDevice::readData(char *data, qint64 len) +{ + Q_D(QFileDevice); + unsetError(); + if (!d->ensureFlushed()) + return -1; + + const qint64 read = d->fileEngine->read(data, len); + if (read < 0) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::ReadError; + d->setError(err, d->fileEngine->errorString()); + } + + if (read < len) { + // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked + d->cachedSize = 0; + } + + return read; +} + +/*! + \internal +*/ +bool QFileDevicePrivate::putCharHelper(char c) +{ +#ifdef QT_NO_QOBJECT + return QIODevicePrivate::putCharHelper(c); +#else + + // Cutoff for code that doesn't only touch the buffer. + int writeBufferSize = writeBuffer.size(); + if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE +#ifdef Q_OS_WIN + || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE) +#endif + ) { + return QIODevicePrivate::putCharHelper(c); + } + + if (!(openMode & QIODevice::WriteOnly)) { + if (openMode == QIODevice::NotOpen) + qWarning("QIODevice::putChar: Closed device"); + else + qWarning("QIODevice::putChar: ReadOnly device"); + return false; + } + + // Make sure the device is positioned correctly. + const bool sequential = isSequential(); + if (pos != devicePos && !sequential && !q_func()->seek(pos)) + return false; + + lastWasWrite = true; + + int len = 1; +#ifdef Q_OS_WIN + if ((openMode & QIODevice::Text) && c == '\n') { + ++len; + *writeBuffer.reserve(1) = '\r'; + } +#endif + + // Write to buffer. + *writeBuffer.reserve(1) = c; + + if (!sequential) { + pos += len; + devicePos += len; + if (!buffer.isEmpty()) + buffer.skip(len); + } + + return true; +#endif +} + +/*! + \reimp +*/ +qint64 QFileDevice::writeData(const char *data, qint64 len) +{ + Q_D(QFileDevice); + unsetError(); + d->lastWasWrite = true; + bool buffered = !(d->openMode & Unbuffered); + + // Flush buffered data if this read will overflow. + if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) { + if (!flush()) + return -1; + } + + // Write directly to the engine if the block size is larger than + // the write buffer size. + if (!buffered || len > QFILE_WRITEBUFFER_SIZE) { + const qint64 ret = d->fileEngine->write(data, len); + if (ret < 0) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::WriteError; + d->setError(err, d->fileEngine->errorString()); + } + return ret; + } + + // Write to the buffer. + char *writePointer = d->writeBuffer.reserve(len); + if (len == 1) + *writePointer = *data; + else + ::memcpy(writePointer, data, len); + return len; +} + +/*! + Returns the file error status. + + The I/O device status returns an error code. For example, if open() + returns false, or a read/write operation returns -1, this function can + be called to find out the reason why the operation failed. + + \sa unsetError() +*/ +QFileDevice::FileError QFileDevice::error() const +{ + Q_D(const QFileDevice); + return d->error; +} + +/*! + Sets the file's error to QFileDevice::NoError. + + \sa error() +*/ +void QFileDevice::unsetError() +{ + Q_D(QFileDevice); + d->setError(QFileDevice::NoError); +} + +/*! + Returns the size of the file. + + For regular empty files on Unix (e.g. those in \c /proc), this function + returns 0; the contents of such a file are generated on demand in response + to you calling read(). +*/ +qint64 QFileDevice::size() const +{ + Q_D(const QFileDevice); + if (!d->ensureFlushed()) + return 0; + d->cachedSize = d->engine()->size(); + return d->cachedSize; +} + +/*! + Sets the file size (in bytes) \a sz. Returns true if the file if the + resize succeeds; false otherwise. If \a sz is larger than the file + currently is the new bytes will be set to 0, if \a sz is smaller the + file is simply truncated. + + \sa size() +*/ +bool QFileDevice::resize(qint64 sz) +{ + Q_D(QFileDevice); + if (!d->ensureFlushed()) + return false; + d->engine(); + if (isOpen() && d->fileEngine->pos() > sz) + seek(sz); + if (d->fileEngine->setSize(sz)) { + unsetError(); + d->cachedSize = sz; + return true; + } + d->cachedSize = 0; + d->setError(QFile::ResizeError, d->fileEngine->errorString()); + return false; +} + +/*! + Returns the complete OR-ed together combination of + QFile::Permission for the file. + + \sa setPermissions() +*/ +QFile::Permissions QFileDevice::permissions() const +{ + Q_D(const QFileDevice); + QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask; + return QFile::Permissions((int)perms); //ewww +} + +/*! + Sets the permissions for the file to the \a permissions specified. + Returns true if successful, or false if the permissions cannot be + modified. + + \sa permissions() +*/ +bool QFileDevice::setPermissions(Permissions permissions) +{ + Q_D(QFileDevice); + if (d->engine()->setPermissions(permissions)) { + unsetError(); + return true; + } + d->setError(QFile::PermissionsError, d->fileEngine->errorString()); + return false; +} + +/*! + \enum QFileDevice::MemoryMapFlags + \since 4.4 + + This enum describes special options that may be used by the map() + function. + + \value NoOptions No options. +*/ + +/*! + Maps \a size bytes of the file into memory starting at \a offset. A file + should be open for a map to succeed but the file does not need to stay + open after the memory has been mapped. When the QFile is destroyed + or a new file is opened with this object, any maps that have not been + unmapped will automatically be unmapped. + + Any mapping options can be passed through \a flags. + + Returns a pointer to the memory or 0 if there is an error. + + \note On Windows CE 5.0 the file will be closed before mapping occurs. + + \sa unmap() + */ +uchar *QFileDevice::map(qint64 offset, qint64 size, MemoryMapFlags flags) +{ + Q_D(QFileDevice); + if (d->engine() + && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) { + unsetError(); + uchar *address = d->fileEngine->map(offset, size, flags); + if (address == 0) + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); + return address; + } + return 0; +} + +/*! + Unmaps the memory \a address. + + Returns true if the unmap succeeds; false otherwise. + + \sa map() + */ +bool QFileDevice::unmap(uchar *address) +{ + Q_D(QFileDevice); + if (d->engine() + && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) { + unsetError(); + bool success = d->fileEngine->unmap(address); + if (!success) + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); + return success; + } + d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension")); + return false; +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h new file mode 100644 index 0000000000..bbde91842c --- /dev/null +++ b/src/corelib/io/qfiledevice.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILEDEVICE_H +#define QFILEDEVICE_H + +#include <QtCore/qiodevice.h> +#include <QtCore/qstring.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QFileDevicePrivate; + +class Q_CORE_EXPORT QFileDevice : public QIODevice +{ +#ifndef QT_NO_QOBJECT + Q_OBJECT +#endif + Q_DECLARE_PRIVATE(QFileDevice) + +public: + enum FileError { + NoError = 0, + ReadError = 1, + WriteError = 2, + FatalError = 3, + ResourceError = 4, + OpenError = 5, + AbortError = 6, + TimeOutError = 7, + UnspecifiedError = 8, + RemoveError = 9, + RenameError = 10, + PositionError = 11, + ResizeError = 12, + PermissionsError = 13, + CopyError = 14 + }; + + enum Permission { + ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000, + ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100, + ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010, + ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001 + }; + Q_DECLARE_FLAGS(Permissions, Permission) + + enum FileHandleFlag { + AutoCloseHandle = 0x0001, + DontCloseHandle = 0 + }; + Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag) + + ~QFileDevice(); + + FileError error() const; + void unsetError(); + + virtual void close(); + + bool isSequential() const; + + int handle() const; + virtual QString fileName() const; + + qint64 pos() const; + bool seek(qint64 offset); + bool atEnd() const; + bool flush(); + + qint64 size() const; + + virtual bool resize(qint64 sz); + virtual Permissions permissions() const; + virtual bool setPermissions(Permissions permissionSpec); + + enum MemoryMapFlags { + NoOptions = 0 + }; + + uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions); + bool unmap(uchar *address); + +protected: + QFileDevice(); +#ifdef QT_NO_QOBJECT + QFileDevice(QFileDevicePrivate &dd); +#else + explicit QFileDevice(QObject *parent); + QFileDevice(QFileDevicePrivate &dd, QObject *parent = 0); +#endif + + qint64 readData(char *data, qint64 maxlen); + qint64 writeData(const char *data, qint64 len); + qint64 readLineData(char *data, qint64 maxlen); + +private: + Q_DISABLE_COPY(QFileDevice) +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDevice::Permissions) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFILEDEVICE_H diff --git a/src/corelib/io/qfiledevice_p.h b/src/corelib/io/qfiledevice_p.h new file mode 100644 index 0000000000..2550cd73a2 --- /dev/null +++ b/src/corelib/io/qfiledevice_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILEDEVICE_P_H +#define QFILEDEVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qiodevice_p.h" +#include "private/qringbuffer_p.h" + +QT_BEGIN_NAMESPACE + +class QAbstractFileEngine; +class QFSFileEngine; + +class QFileDevicePrivate : public QIODevicePrivate +{ + Q_DECLARE_PUBLIC(QFileDevice) +protected: + QFileDevicePrivate(); + ~QFileDevicePrivate(); + + virtual QAbstractFileEngine *engine() const; + + QFileDevice::FileHandleFlags handleFlags; + + mutable QAbstractFileEngine *fileEngine; + bool lastWasWrite; + QRingBuffer writeBuffer; + inline bool ensureFlushed() const; + + bool putCharHelper(char c); + + QFileDevice::FileError error; + void setError(QFileDevice::FileError err); + void setError(QFileDevice::FileError err, const QString &errorString); + void setError(QFileDevice::FileError err, int errNum); + + mutable qint64 cachedSize; +}; + +inline bool QFileDevicePrivate::ensureFlushed() const +{ + // This function ensures that the write buffer has been flushed (const + // because certain const functions need to call it. + if (lastWasWrite) { + const_cast<QFileDevicePrivate *>(this)->lastWasWrite = false; + if (!const_cast<QFileDevice *>(q_func())->flush()) + return false; + } + return true; +} + +QT_END_NAMESPACE + +#endif // QFILEDEVICE_P_H |