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
21namespace Utils
22{
23
24static const QLatin1Char s_slash('/');
25
26inline 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 */
46inline 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
72inline void removeTrailingSlash(QString &path)
73{
74 if (path.endsWith(c: QLatin1Char('/'))) {
75 path.chop(n: 1);
76 }
77}
78
79inline QString trailingSlashRemoved(QString &&path)
80{
81 removeTrailingSlash(path);
82 return path;
83}
84
85inline 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 */
96inline 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()
107inline 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
120inline 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
133inline 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
146inline 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
160inline bool isRegFileMask(mode_t mode)
161{
162 return (mode & QT_STAT_MASK) == QT_STAT_REG;
163}
164
165inline bool isDirMask(mode_t mode)
166{
167 return (mode & QT_STAT_MASK) == QT_STAT_DIR;
168}
169
170inline 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

source code of kio/src/utils_p.h