1 | /* |
2 | This file is part of the KDE project. |
3 | SPDX-FileCopyrightText: 2017 Anthony Fieroni <bvbfan@abv.bg> |
4 | SPDX-FileCopyrightText: 2022 Ahmad Samir <a.samirh78@gmail.com> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-or-later |
7 | */ |
8 | |
9 | #ifndef KIO_UTILS_P_H |
10 | #define KIO_UTILS_P_H |
11 | |
12 | #include <QDir> |
13 | #include <QString> |
14 | #include <QUrl> |
15 | #include <QtGlobal> |
16 | #include <qplatformdefs.h> |
17 | |
18 | // QT_STAT_LNK on Windows MinGW |
19 | #include "kioglobal_p.h" |
20 | |
21 | namespace Utils |
22 | { |
23 | |
24 | static const QLatin1Char s_slash('/'); |
25 | |
26 | inline bool isAbsoluteLocalPath(const QString &path) |
27 | { |
28 | // QDir::isAbsolutePath() will return true if "path" starts with ':', the latter denotes a |
29 | // Qt Resource (qrc). |
30 | // "Local" as in on local disk not in memory (qrc) |
31 | return !path.startsWith(c: QLatin1Char(':')) && QDir::isAbsolutePath(path); |
32 | } |
33 | |
34 | /** |
35 | * Appends a slash to @p path if it's not empty, and doesn't already end with a '/'. |
36 | * This method modifies its arg directly: |
37 | * QString p = "foo"; |
38 | * appenSlash(p); // Now p is "foo/" |
39 | * |
40 | * For `const QString&` use slashAppended(). |
41 | * |
42 | * All the slash-related methods are modeled after: |
43 | * - QString::chop(), which modifies the string it's called on, and returns void |
44 | * - QString::chopped(), which takes a copy, modifies it, and return it |
45 | */ |
46 | inline void appendSlash(QString &path) |
47 | { |
48 | if (path.isEmpty()) { |
49 | Q_ASSERT_X(false, Q_FUNC_INFO, "Not appending '/' to an empty string" ); |
50 | return; |
51 | } |
52 | |
53 | const auto slash = QLatin1Char('/'); |
54 | if (!path.endsWith(c: slash)) { |
55 | path += slash; |
56 | } |
57 | } |
58 | |
59 | [[nodiscard]] inline QString slashAppended(QString &&path) |
60 | { |
61 | appendSlash(path); |
62 | return path; |
63 | } |
64 | |
65 | [[nodiscard]] inline QString slashAppended(const QString &s) |
66 | { |
67 | QString path{s}; |
68 | appendSlash(path); |
69 | return path; |
70 | } |
71 | |
72 | inline void removeTrailingSlash(QString &path) |
73 | { |
74 | if (path.endsWith(c: QLatin1Char('/'))) { |
75 | path.chop(n: 1); |
76 | } |
77 | } |
78 | |
79 | inline QString trailingSlashRemoved(QString &&path) |
80 | { |
81 | removeTrailingSlash(path); |
82 | return path; |
83 | } |
84 | |
85 | inline QString trailingSlashRemoved(const QString &s) |
86 | { |
87 | QString path = s; |
88 | removeTrailingSlash(path); |
89 | return path; |
90 | } |
91 | |
92 | /** |
93 | * Appends a slash '/' to @p url path, if url.path() isn't empty and doesn't already |
94 | * end with a slash. |
95 | */ |
96 | inline void appendSlashToPath(QUrl &url) |
97 | { |
98 | const auto slash = QLatin1Char('/'); |
99 | QString path = url.path(); |
100 | if (!path.isEmpty() && !path.endsWith(c: slash)) { |
101 | appendSlash(path); |
102 | url.setPath(path); |
103 | } |
104 | } |
105 | |
106 | // concatPaths() |
107 | inline QString concatPaths(const QString &path1, const QString &path2) |
108 | { |
109 | Q_ASSERT(!path2.startsWith(QLatin1Char('/'))); |
110 | |
111 | if (path1.isEmpty()) { |
112 | return path2; |
113 | } |
114 | |
115 | QString ret = slashAppended(s: path1); |
116 | ret += path2; |
117 | return ret; |
118 | } |
119 | |
120 | inline QString concatPaths(QString &&path1, const QString &path2) |
121 | { |
122 | Q_ASSERT(!path2.startsWith(s_slash)); |
123 | |
124 | if (path1.isEmpty()) { |
125 | return path2; |
126 | } |
127 | |
128 | appendSlash(path&: path1); |
129 | path1 += path2; |
130 | return path1; |
131 | } |
132 | |
133 | inline QString concatPaths(const QString &path1, QString &&path2) |
134 | { |
135 | Q_ASSERT(!path2.startsWith(s_slash)); |
136 | |
137 | if (path1.isEmpty()) { |
138 | return path2; |
139 | } |
140 | |
141 | path2.prepend(c: s_slash); |
142 | path2.prepend(s: path1); |
143 | return path2; |
144 | } |
145 | |
146 | inline QString concatPaths(QString &&path1, QString &&path2) |
147 | { |
148 | Q_ASSERT(!path2.startsWith(s_slash)); |
149 | |
150 | if (path1.isEmpty()) { |
151 | return path2; |
152 | } |
153 | |
154 | appendSlash(path&: path1); |
155 | path1 += path2; |
156 | return path1; |
157 | } |
158 | |
159 | // mode_t |
160 | inline bool isRegFileMask(mode_t mode) |
161 | { |
162 | return (mode & QT_STAT_MASK) == QT_STAT_REG; |
163 | } |
164 | |
165 | inline bool isDirMask(mode_t mode) |
166 | { |
167 | return (mode & QT_STAT_MASK) == QT_STAT_DIR; |
168 | } |
169 | |
170 | inline bool isLinkMask(mode_t mode) |
171 | { |
172 | return (mode & QT_STAT_MASK) == QT_STAT_LNK; |
173 | } |
174 | |
175 | } // namespace |
176 | |
177 | #endif // KIO_UTILS_P_H |
178 | |