File indexing completed on 2024-12-01 09:53:48

0001 /*
0002     This file is part of the KDE project.
0003     SPDX-FileCopyrightText: 2017 Anthony Fieroni <bvbfan@abv.bg>
0004     SPDX-FileCopyrightText: 2022 Ahmad Samir <a.samirh78@gmail.com>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KIO_UTILS_P_H
0010 #define KIO_UTILS_P_H
0011 
0012 #include <QDir>
0013 #include <QString>
0014 #include <QUrl>
0015 #include <QtGlobal>
0016 #include <qplatformdefs.h>
0017 
0018 // QT_STAT_LNK on Windows MinGW
0019 #include "kioglobal_p.h"
0020 
0021 namespace Utils
0022 {
0023 
0024 static const QLatin1Char s_slash('/');
0025 
0026 inline bool isAbsoluteLocalPath(const QString &path)
0027 {
0028     // QDir::isAbsolutePath() will return true if "path" starts with ':', the latter denotes a
0029     // Qt Resource (qrc).
0030     // "Local" as in on local disk not in memory (qrc)
0031     return !path.startsWith(QLatin1Char(':')) && QDir::isAbsolutePath(path);
0032 }
0033 
0034 /**
0035  * Appends a slash to @p path if it's not empty, and doesn't already end with a '/'.
0036  * This method modifies its arg directly:
0037  * QString p = "foo";
0038  * appenSlash(p); // Now p is "foo/"
0039  *
0040  * For `const QString&` use slashAppended().
0041  *
0042  * All the slash-related methods are modeled after:
0043  * - QString::chop(), which modifies the string it's called on, and returns void
0044  * - QString::chopped(), which takes a copy, modifies it, and return it
0045  */
0046 inline void appendSlash(QString &path)
0047 {
0048     if (path.isEmpty()) {
0049         Q_ASSERT_X(false, Q_FUNC_INFO, "Not appending '/' to an empty string");
0050         return;
0051     }
0052 
0053     const auto slash = QLatin1Char('/');
0054     if (!path.endsWith(slash)) {
0055         path += slash;
0056     }
0057 }
0058 
0059 [[nodiscard]] inline QString slashAppended(QString &&path)
0060 {
0061     appendSlash(path);
0062     return path;
0063 }
0064 
0065 [[nodiscard]] inline QString slashAppended(const QString &s)
0066 {
0067     QString path{s};
0068     appendSlash(path);
0069     return path;
0070 }
0071 
0072 inline void removeTrailingSlash(QString &path)
0073 {
0074     if (path.endsWith(QLatin1Char('/'))) {
0075         path.chop(1);
0076     }
0077 }
0078 
0079 inline QString trailingSlashRemoved(QString &&path)
0080 {
0081     removeTrailingSlash(path);
0082     return path;
0083 }
0084 
0085 inline QString trailingSlashRemoved(const QString &s)
0086 {
0087     QString path = s;
0088     removeTrailingSlash(path);
0089     return path;
0090 }
0091 
0092 /**
0093  * Appends a slash '/' to @p url path, if url.path() isn't empty and doesn't already
0094  * end with a slash.
0095  */
0096 inline void appendSlashToPath(QUrl &url)
0097 {
0098     const auto slash = QLatin1Char('/');
0099     QString path = url.path();
0100     if (!path.isEmpty() && !path.endsWith(slash)) {
0101         appendSlash(path);
0102         url.setPath(path);
0103     }
0104 }
0105 
0106 // concatPaths()
0107 inline QString concatPaths(const QString &path1, const QString &path2)
0108 {
0109     Q_ASSERT(!path2.startsWith(QLatin1Char('/')));
0110 
0111     if (path1.isEmpty()) {
0112         return path2;
0113     }
0114 
0115     QString ret = slashAppended(path1);
0116     ret += path2;
0117     return ret;
0118 }
0119 
0120 inline QString concatPaths(QString &&path1, const QString &path2)
0121 {
0122     Q_ASSERT(!path2.startsWith(s_slash));
0123 
0124     if (path1.isEmpty()) {
0125         return path2;
0126     }
0127 
0128     appendSlash(path1);
0129     path1 += path2;
0130     return path1;
0131 }
0132 
0133 inline QString concatPaths(const QString &path1, QString &&path2)
0134 {
0135     Q_ASSERT(!path2.startsWith(s_slash));
0136 
0137     if (path1.isEmpty()) {
0138         return path2;
0139     }
0140 
0141     path2.prepend(s_slash);
0142     path2.prepend(path1);
0143     return path2;
0144 }
0145 
0146 inline QString concatPaths(QString &&path1, QString &&path2)
0147 {
0148     Q_ASSERT(!path2.startsWith(s_slash));
0149 
0150     if (path1.isEmpty()) {
0151         return path2;
0152     }
0153 
0154     appendSlash(path1);
0155     path1 += path2;
0156     return path1;
0157 }
0158 
0159 // mode_t
0160 inline bool isRegFileMask(mode_t mode)
0161 {
0162     return (mode & QT_STAT_MASK) == QT_STAT_REG;
0163 }
0164 
0165 inline bool isDirMask(mode_t mode)
0166 {
0167     return (mode & QT_STAT_MASK) == QT_STAT_DIR;
0168 }
0169 
0170 inline bool isLinkMask(mode_t mode)
0171 {
0172     return (mode & QT_STAT_MASK) == QT_STAT_LNK;
0173 }
0174 
0175 } // namespace
0176 
0177 #endif // KIO_UTILS_P_H