1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#ifndef QTBASE_DEPFILE_SHARED_H
5#define QTBASE_DEPFILE_SHARED_H
6
7#include <QByteArray>
8#include <QString>
9#include <QFile>
10
11// Escape characters in given path. Dependency paths are Make-style, not NMake/Jom style.
12// The paths can also be consumed by Ninja.
13// "$" replaced by "$$"
14// "#" replaced by "\#"
15// " " replaced by "\ "
16// "\#" replaced by "\\#"
17// "\ " replaced by "\\\ "
18//
19// The escape rules are according to what clang / llvm escapes when generating a Make-style
20// dependency file.
21// Is a template function, because input param can be either a QString or a QByteArray.
22template <typename T> struct CharType;
23template <> struct CharType<QString> { using type = QLatin1Char; };
24template <> struct CharType<QByteArray> { using type = char; };
25template <typename StringType>
26StringType escapeDependencyPath(const StringType &path)
27{
28 using CT = typename CharType<StringType>::type;
29 StringType escapedPath;
30 int size = path.size();
31 escapedPath.reserve(size);
32 for (int i = 0; i < size; ++i) {
33 if (path[i] == CT('$')) {
34 escapedPath.append(CT('$'));
35 } else if (path[i] == CT('#')) {
36 escapedPath.append(CT('\\'));
37 } else if (path[i] == CT(' ')) {
38 escapedPath.append(CT('\\'));
39 int backwards_it = i - 1;
40 while (backwards_it > 0 && path[backwards_it] == CT('\\')) {
41 escapedPath.append(CT('\\'));
42 --backwards_it;
43 }
44 }
45 escapedPath.append(path[i]);
46 }
47 return escapedPath;
48}
49
50static inline QByteArray escapeAndEncodeDependencyPath(const QString &path)
51{
52 return QFile::encodeName(fileName: escapeDependencyPath(path));
53}
54
55#endif // QTBASE_DEPFILE_SHARED_H
56

source code of qtbase/src/tools/shared/depfile_shared.h