/src/CMake/Source/cmCMakePath.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | |
4 | | #include "cmConfigure.h" // IWYU pragma: keep |
5 | | |
6 | | #include "cmCMakePath.h" |
7 | | |
8 | | #include <string> |
9 | | |
10 | | #include "cmStringAlgorithms.h" |
11 | | |
12 | | #if defined(_WIN32) |
13 | | # include <cstdlib> |
14 | | #endif |
15 | | |
16 | | #include <cm/filesystem> |
17 | | #include <cm/string_view> |
18 | | |
19 | | #if defined(_WIN32) |
20 | | # include <cmext/string_view> |
21 | | |
22 | | #endif |
23 | | |
24 | | cmCMakePath& cmCMakePath::ReplaceWideExtension(cm::string_view extension) |
25 | 0 | { |
26 | 0 | auto file = this->Path.filename().string(); |
27 | 0 | if (!file.empty() && file != "." && file != "..") { |
28 | 0 | auto pos = file.find('.', file[0] == '.' ? 1 : 0); |
29 | 0 | if (pos != std::string::npos) { |
30 | 0 | file.erase(pos); |
31 | 0 | } |
32 | 0 | } |
33 | 0 | if (!extension.empty()) { |
34 | 0 | if (extension[0] != '.') { |
35 | 0 | file += '.'; |
36 | 0 | } |
37 | 0 | file = cmStrCat(std::move(file), extension); |
38 | 0 | } |
39 | 0 | this->Path.replace_filename(file); |
40 | 0 | return *this; |
41 | 0 | } |
42 | | |
43 | | cmCMakePath cmCMakePath::GetWideExtension() const |
44 | 0 | { |
45 | 0 | auto file = this->Path.filename().string(); |
46 | 0 | if (file.empty() || file == "." || file == "..") { |
47 | 0 | return cmCMakePath{}; |
48 | 0 | } |
49 | | |
50 | 0 | auto pos = file.find('.', file[0] == '.' ? 1 : 0); |
51 | 0 | if (pos != std::string::npos) { |
52 | 0 | return cm::string_view(file.data() + pos, file.length() - pos); |
53 | 0 | } |
54 | | |
55 | 0 | return cmCMakePath{}; |
56 | 0 | } |
57 | | |
58 | | cmCMakePath cmCMakePath::GetNarrowStem() const |
59 | 0 | { |
60 | 0 | auto stem = this->Path.stem().string(); |
61 | 0 | if (stem.empty() || stem == "." || stem == "..") { |
62 | 0 | return stem; |
63 | 0 | } |
64 | | |
65 | 0 | auto pos = stem.find('.', stem[0] == '.' ? 1 : 0); |
66 | 0 | if (pos != std::string::npos) { |
67 | 0 | return stem.substr(0, pos); |
68 | 0 | } |
69 | 0 | return stem; |
70 | 0 | } |
71 | | |
72 | | cmCMakePath cmCMakePath::Absolute(cm::filesystem::path const& base) const |
73 | 0 | { |
74 | 0 | if (this->Path.is_relative()) { |
75 | 0 | auto path = base; |
76 | 0 | path /= this->Path; |
77 | | // filesystem::path::operator/= use preferred_separator ('\' on Windows) |
78 | | // so converts back to '/' |
79 | 0 | return path.generic_string(); |
80 | 0 | } |
81 | 0 | return *this; |
82 | 0 | } |
83 | | |
84 | | bool cmCMakePath::IsPrefix(cmCMakePath const& path) const |
85 | 0 | { |
86 | 0 | auto prefix_it = this->Path.begin(); |
87 | 0 | auto prefix_end = this->Path.end(); |
88 | 0 | auto path_it = path.Path.begin(); |
89 | 0 | auto path_end = path.Path.end(); |
90 | |
|
91 | 0 | while (prefix_it != prefix_end && path_it != path_end && |
92 | 0 | *prefix_it == *path_it) { |
93 | 0 | ++prefix_it; |
94 | 0 | ++path_it; |
95 | 0 | } |
96 | 0 | return (prefix_it == prefix_end) || |
97 | 0 | (prefix_it->empty() && path_it != path_end); |
98 | 0 | } |
99 | | |
100 | | std::string cmCMakePath::FormatPath(std::string path, format fmt) |
101 | 1.39k | { |
102 | | #if defined(_WIN32) |
103 | | if (fmt == auto_format || fmt == native_format) { |
104 | | auto prefix = path.substr(0, 4); |
105 | | for (auto& c : prefix) { |
106 | | if (c == '\\') { |
107 | | c = '/'; |
108 | | } |
109 | | } |
110 | | // remove Windows long filename marker |
111 | | if (prefix == "//?/"_s) { |
112 | | path.erase(0, 4); |
113 | | } |
114 | | if (cmHasPrefix(path, "UNC/"_s) || cmHasPrefix(path, "UNC\\"_s)) { |
115 | | path.erase(0, 2); |
116 | | path[0] = '/'; |
117 | | } |
118 | | } |
119 | | #else |
120 | 1.39k | static_cast<void>(fmt); |
121 | 1.39k | #endif |
122 | 1.39k | return path; |
123 | 1.39k | } |
124 | | |
125 | | void cmCMakePath::GetNativePath(std::string& path) const |
126 | 0 | { |
127 | 0 | cm::filesystem::path tmp(this->Path); |
128 | 0 | tmp.make_preferred(); |
129 | |
|
130 | 0 | path = tmp.string(); |
131 | 0 | } |
132 | | void cmCMakePath::GetNativePath(std::wstring& path) const |
133 | 0 | { |
134 | 0 | cm::filesystem::path tmp(this->Path); |
135 | 0 | tmp.make_preferred(); |
136 | |
|
137 | 0 | path = tmp.wstring(); |
138 | |
|
139 | | #if defined(_WIN32) |
140 | | // Windows long filename |
141 | | static std::wstring UNC(L"\\\\?\\UNC"); |
142 | | static std::wstring PREFIX(L"\\\\?\\"); |
143 | | |
144 | | if (this->IsAbsolute() && path.length() > _MAX_PATH - 12) { |
145 | | if (this->HasRootName() && path[0] == L'\\') { |
146 | | path = UNC + path.substr(1); |
147 | | } else { |
148 | | path = PREFIX + path; |
149 | | } |
150 | | } |
151 | | #endif |
152 | 0 | } |