summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfilesystementry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qfilesystementry.cpp')
-rw-r--r--src/corelib/io/qfilesystementry.cpp383
1 files changed, 383 insertions, 0 deletions
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
new file mode 100644
index 0000000000..ccbb10d82c
--- /dev/null
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystementry_p.h"
+
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/private/qfsfileengine_p.h>
+#ifdef Q_OS_WIN
+#include <QtCore/qstringbuilder.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+static bool isUncRoot(const QString &server)
+{
+ QString localPath = QDir::toNativeSeparators(server);
+ if (!localPath.startsWith(QLatin1String("\\\\")))
+ return false;
+
+ int idx = localPath.indexOf(QLatin1Char('\\'), 2);
+ if (idx == -1 || idx + 1 == localPath.length())
+ return true;
+
+ localPath = localPath.right(localPath.length() - idx - 1).trimmed();
+ return localPath.isEmpty();
+}
+
+static inline QString fixIfRelativeUncPath(const QString &path)
+{
+ QString currentPath = QDir::currentPath();
+ if (currentPath.startsWith(QLatin1String("//")))
+ return currentPath % QChar(QLatin1Char('/')) % path;
+ return path;
+}
+#endif
+
+QFileSystemEntry::QFileSystemEntry()
+ : m_lastSeparator(0),
+ m_firstDotInFileName(0),
+ m_lastDotInFileName(0)
+{
+}
+
+/*!
+ \internal
+ Use this constructor when the path is supplied by user code, as it may contain a mix
+ of '/' and the native separator.
+ */
+QFileSystemEntry::QFileSystemEntry(const QString &filePath)
+ : m_filePath(QDir::fromNativeSeparators(filePath)),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+/*!
+ \internal
+ Use this constructor when the path is guaranteed to be in internal format, i.e. all
+ directory separators are '/' and not the native separator.
+ */
+QFileSystemEntry::QFileSystemEntry(const QString &filePath, FromInternalPath /* dummy */)
+ : m_filePath(filePath),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+/*!
+ \internal
+ Use this constructor when the path comes from a native API
+ */
+QFileSystemEntry::QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath /* dummy */)
+ : m_nativeFilePath(nativeFilePath),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath)
+ : m_filePath(QDir::fromNativeSeparators(filePath)),
+ m_nativeFilePath(nativeFilePath),
+ m_lastSeparator(-2),
+ m_firstDotInFileName(-2),
+ m_lastDotInFileName(0)
+{
+}
+
+QString QFileSystemEntry::filePath() const
+{
+ resolveFilePath();
+ return m_filePath;
+}
+
+QFileSystemEntry::NativePath QFileSystemEntry::nativeFilePath() const
+{
+ resolveNativeFilePath();
+ return m_nativeFilePath;
+}
+
+void QFileSystemEntry::resolveFilePath() const
+{
+ if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
+#if defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
+ m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
+#ifdef Q_OS_WIN
+ if (m_filePath.startsWith(QLatin1String("//?/UNC/")))
+ m_filePath = m_filePath.remove(2,6);
+ if (m_filePath.startsWith(QLatin1String("//?/")))
+ m_filePath = m_filePath.remove(0,4);
+#endif
+#else
+ m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
+#endif
+ }
+}
+
+void QFileSystemEntry::resolveNativeFilePath() const
+{
+ if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) {
+#ifdef Q_OS_WIN
+ QString filePath = m_filePath;
+ if (isRelative())
+ filePath = fixIfRelativeUncPath(m_filePath);
+ m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath));
+#elif defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
+ m_nativeFilePath = QDir::toNativeSeparators(m_filePath);
+#else
+ m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath));
+#endif
+ }
+}
+
+QString QFileSystemEntry::fileName() const
+{
+ findLastSeparator();
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.mid(2);
+#endif
+ return m_filePath.mid(m_lastSeparator + 1);
+}
+
+QString QFileSystemEntry::path() const
+{
+ findLastSeparator();
+ if (m_lastSeparator == -1) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.left(2);
+#endif
+ return QString(QLatin1Char('.'));
+ }
+ if (m_lastSeparator == 0)
+ return QString(QLatin1Char('/'));
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.left(m_lastSeparator + 1);
+#endif
+ return m_filePath.left(m_lastSeparator);
+}
+
+QString QFileSystemEntry::baseName() const
+{
+ findFileNameSeparators();
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.mid(2);
+#endif
+ int length = -1;
+ if (m_firstDotInFileName >= 0) {
+ length = m_firstDotInFileName;
+ if (m_lastSeparator != -1) // avoid off by one
+ length--;
+ }
+ return m_filePath.mid(m_lastSeparator + 1, length);
+}
+
+QString QFileSystemEntry::completeBaseName() const
+{
+ findFileNameSeparators();
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ return m_filePath.mid(2);
+#endif
+ int length = -1;
+ if (m_firstDotInFileName >= 0) {
+ length = m_firstDotInFileName + m_lastDotInFileName;
+ if (m_lastSeparator != -1) // avoid off by one
+ length--;
+ }
+ return m_filePath.mid(m_lastSeparator + 1, length);
+}
+
+QString QFileSystemEntry::suffix() const
+{
+ findFileNameSeparators();
+
+ if (m_lastDotInFileName == -1)
+ return QString();
+
+ return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1);
+}
+
+QString QFileSystemEntry::completeSuffix() const
+{
+ findFileNameSeparators();
+ if (m_firstDotInFileName == -1)
+ return QString();
+
+ return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1);
+}
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+bool QFileSystemEntry::isRelative() const
+{
+ resolveFilePath();
+ return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath[0].unicode() != '/')
+ && (!(m_filePath.length() >= 2 && m_filePath[1].unicode() == ':'))));
+}
+
+bool QFileSystemEntry::isAbsolute() const
+{
+ resolveFilePath();
+ return (!m_filePath.isEmpty() && ((m_filePath.length() >= 3
+ && (m_filePath[0].isLetter() && m_filePath[1].unicode() == ':' && m_filePath[2].unicode() == '/'))
+#ifdef Q_OS_WIN
+ || (m_filePath.length() >= 2 && (m_filePath.at(0) == QLatin1Char('/') && m_filePath.at(1) == QLatin1Char('/')))
+#endif
+ ));
+}
+#else
+bool QFileSystemEntry::isRelative() const
+{
+ return !isAbsolute();
+}
+
+bool QFileSystemEntry::isAbsolute() const
+{
+ resolveFilePath();
+ return (!m_filePath.isEmpty() && (m_filePath[0].unicode() == '/'));
+}
+#endif
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+bool QFileSystemEntry::isDriveRoot() const
+{
+ resolveFilePath();
+ return (m_filePath.length() == 3
+ && m_filePath.at(0).isLetter() && m_filePath.at(1) == QLatin1Char(':')
+ && m_filePath.at(2) == QLatin1Char('/'));
+}
+#endif
+
+bool QFileSystemEntry::isRoot() const
+{
+ resolveFilePath();
+ if (m_filePath == QLatin1String("/")
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ || isDriveRoot()
+#if defined(Q_OS_WIN)
+ || isUncRoot(m_filePath)
+#endif
+#endif
+ )
+ return true;
+
+ return false;
+}
+
+bool QFileSystemEntry::isEmpty() const
+{
+ resolveNativeFilePath();
+ return m_nativeFilePath.isEmpty();
+}
+
+// private methods
+
+void QFileSystemEntry::findLastSeparator() const
+{
+ if (m_lastSeparator == -2) {
+ resolveFilePath();
+ m_lastSeparator = -1;
+ for (int i = m_filePath.size() - 1; i >= 0; --i) {
+ if (m_filePath[i].unicode() == '/') {
+ m_lastSeparator = i;
+ break;
+ }
+ }
+ }
+}
+
+void QFileSystemEntry::findFileNameSeparators() const
+{
+ if (m_firstDotInFileName == -2) {
+ resolveFilePath();
+ int firstDotInFileName = -1;
+ int lastDotInFileName = -1;
+ int lastSeparator = m_lastSeparator;
+
+ int stop;
+ if (lastSeparator < 0) {
+ lastSeparator = -1;
+ stop = 0;
+ } else {
+ stop = lastSeparator;
+ }
+
+ int i = m_filePath.size() - 1;
+ for (; i >= stop; --i) {
+ if (m_filePath[i].unicode() == '.') {
+ firstDotInFileName = lastDotInFileName = i;
+ break;
+ } else if (m_filePath[i].unicode() == '/') {
+ lastSeparator = i;
+ break;
+ }
+ }
+
+ if (lastSeparator != i) {
+ for (--i; i >= stop; --i) {
+ if (m_filePath[i].unicode() == '.')
+ firstDotInFileName = i;
+ else if (m_filePath[i].unicode() == '/') {
+ lastSeparator = i;
+ break;
+ }
+ }
+ }
+ m_lastSeparator = lastSeparator;
+ m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator);
+ if (lastDotInFileName == -1)
+ m_lastDotInFileName = -1;
+ else if (firstDotInFileName == lastDotInFileName)
+ m_lastDotInFileName = 0;
+ else
+ m_lastDotInFileName = lastDotInFileName - firstDotInFileName;
+ }
+}
+
+QT_END_NAMESPACE