/src/CMake/Source/cmCMakePath.h
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 | | #pragma once |
5 | | |
6 | | #include "cmConfigure.h" // IWYU pragma: keep |
7 | | |
8 | | #include <cstddef> |
9 | | #include <string> |
10 | | #include <utility> |
11 | | |
12 | | #include <cm/filesystem> |
13 | | #include <cm/string_view> |
14 | | #include <cm/type_traits> |
15 | | |
16 | | namespace cm { |
17 | | class static_string_view; |
18 | | } |
19 | | |
20 | | namespace detail { |
21 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
22 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc fails to compile |
23 | | // the full 'is_pathable' and 'is_move_pathable' checks. We use it only to |
24 | | // improve error messages via 'enable_if' when calling methods with incorrect |
25 | | // types. Just pretend all types are allowed so we can at least compile valid |
26 | | // code. |
27 | | template <typename T> |
28 | | struct is_pathable : std::true_type |
29 | | { |
30 | | }; |
31 | | |
32 | | template <typename T> |
33 | | struct is_move_pathable : std::true_type |
34 | | { |
35 | | }; |
36 | | |
37 | | #else |
38 | | template <typename T, typename = void> |
39 | | struct is_pathable : std::false_type |
40 | | { |
41 | | }; |
42 | | |
43 | | template <> |
44 | | struct is_pathable<cm::filesystem::path> : std::true_type |
45 | | { |
46 | | }; |
47 | | template <> |
48 | | struct is_pathable<std::string> : std::true_type |
49 | | { |
50 | | }; |
51 | | template <> |
52 | | struct is_pathable<cm::string_view> : std::true_type |
53 | | { |
54 | | }; |
55 | | template <> |
56 | | struct is_pathable<cm::static_string_view> : std::true_type |
57 | | { |
58 | | }; |
59 | | template <typename T> |
60 | | struct is_pathable< |
61 | | T, |
62 | | cm::enable_if_t<std::is_same<char*, typename std::decay<T>::type>::value, |
63 | | void>> |
64 | | : cm::bool_constant<std::is_same<char*, typename std::decay<T>::type>::value> |
65 | | { |
66 | | }; |
67 | | |
68 | | template <typename T> |
69 | | struct is_move_pathable : std::false_type |
70 | | { |
71 | | }; |
72 | | |
73 | | template <> |
74 | | struct is_move_pathable<cm::filesystem::path> : std::true_type |
75 | | { |
76 | | }; |
77 | | template <> |
78 | | struct is_move_pathable<std::string> : std::true_type |
79 | | { |
80 | | }; |
81 | | #endif |
82 | | } |
83 | | |
84 | | class cmCMakePath |
85 | | { |
86 | | private: |
87 | | template <typename Source> |
88 | | using enable_if_move_pathable = |
89 | | cm::enable_if_t<detail::is_move_pathable<Source>::value, cmCMakePath&>; |
90 | | |
91 | | template <typename Source> |
92 | | using enable_if_pathable = |
93 | | cm::enable_if_t<detail::is_pathable<Source>::value, cmCMakePath&>; |
94 | | |
95 | | public: |
96 | | using value_type = cm::filesystem::path::value_type; |
97 | | using string_type = cm::filesystem::path::string_type; |
98 | | |
99 | | enum format : unsigned char |
100 | | { |
101 | | auto_format = |
102 | | static_cast<unsigned char>(cm::filesystem::path::format::auto_format), |
103 | | native_format = |
104 | | static_cast<unsigned char>(cm::filesystem::path::format::native_format), |
105 | | generic_format = |
106 | | static_cast<unsigned char>(cm::filesystem::path::format::generic_format) |
107 | | }; |
108 | | |
109 | | class iterator; |
110 | | using const_iterator = iterator; |
111 | | |
112 | 0 | cmCMakePath() noexcept = default; |
113 | | |
114 | 348 | cmCMakePath(cmCMakePath const&) = default; |
115 | | |
116 | | cmCMakePath(cmCMakePath&& path) noexcept |
117 | | : Path(std::forward<cm::filesystem::path>(path.Path)) |
118 | 0 | { |
119 | 0 | } |
120 | | |
121 | | cmCMakePath(cm::filesystem::path path) noexcept |
122 | 2.80k | : Path(std::move(path)) |
123 | 2.80k | { |
124 | 2.80k | } |
125 | | cmCMakePath(cm::string_view source, format fmt = generic_format) noexcept |
126 | 0 | : Path(FormatPath(source, fmt)) |
127 | 0 | { |
128 | 0 | } |
129 | | cmCMakePath(char const* source, format fmt = generic_format) noexcept |
130 | 0 | : Path(FormatPath(cm::string_view{ source }, fmt)) |
131 | 0 | { |
132 | 0 | } |
133 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
134 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
135 | | // standard methods and templates use the same name. The template is selected |
136 | | // rather than the standard one regardless the arguments of the method. |
137 | | cmCMakePath(std::string const& source, format fmt = generic_format) |
138 | | : Path(FormatPath(source, fmt)) |
139 | | { |
140 | | } |
141 | | cmCMakePath(std::string&& source, format fmt = generic_format) |
142 | | : Path(FormatPath(std::move(source), fmt)) |
143 | | { |
144 | | } |
145 | | #else |
146 | | template <typename Source, typename = enable_if_move_pathable<Source>> |
147 | | cmCMakePath(Source source, format fmt = generic_format) |
148 | 1.39k | : Path(FormatPath(std::move(source), fmt)) |
149 | 1.39k | { |
150 | 1.39k | } |
151 | | #endif |
152 | | |
153 | | template <typename Source, typename = enable_if_move_pathable<Source>> |
154 | | cmCMakePath& Assign(Source&& source) |
155 | 0 | { |
156 | 0 | this->Path = std::forward<Source>(source); |
157 | 0 | return *this; |
158 | 0 | } |
159 | | template <typename Source, typename = enable_if_pathable<Source>> |
160 | | cmCMakePath& Assign(Source const& source) |
161 | 0 | { |
162 | 0 | this->Path = source; |
163 | 0 | return *this; |
164 | 0 | } Unexecuted instantiation: cmCMakePath& cmCMakePath::Assign<cm::filesystem::path, cmCMakePath&>(cm::filesystem::path const&) Unexecuted instantiation: cmCMakePath& cmCMakePath::Assign<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePath&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
165 | | |
166 | | cmCMakePath& operator=(cmCMakePath const& path) |
167 | 0 | { |
168 | 0 | if (this != &path) { |
169 | 0 | this->Path = path.Path; |
170 | 0 | } |
171 | 0 | return *this; |
172 | 0 | } |
173 | | cmCMakePath& operator=(cmCMakePath&& path) noexcept |
174 | 0 | { |
175 | 0 | if (this != &path) { |
176 | 0 | this->Path = std::move(path.Path); |
177 | 0 | } |
178 | 0 | return *this; |
179 | 0 | } |
180 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
181 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
182 | | // standard methods and templates use the same name. The template is selected |
183 | | // rather than the standard one regardless the arguments of the method. |
184 | | cmCMakePath& operator=(cm::filesystem::path&& source) |
185 | | { |
186 | | this->Assign(std::forward<cm::filesystem::path>(source)); |
187 | | return *this; |
188 | | } |
189 | | cmCMakePath& operator=(std::string&& source) |
190 | | { |
191 | | this->Assign(std::forward<std::string>(source)); |
192 | | return *this; |
193 | | } |
194 | | cmCMakePath& operator=(cm::filesystem::path const& source) |
195 | | { |
196 | | this->Assign(source); |
197 | | return *this; |
198 | | } |
199 | | cmCMakePath& operator=(std::string const& source) |
200 | | { |
201 | | this->Assign(source); |
202 | | return *this; |
203 | | } |
204 | | cmCMakePath& operator=(cm::string_view const source) |
205 | | { |
206 | | this->Assign(source); |
207 | | return *this; |
208 | | } |
209 | | cmCMakePath& operator=(char const* source) |
210 | | { |
211 | | this->Assign(cm::string_view{ source }); |
212 | | return *this; |
213 | | } |
214 | | #else |
215 | | template <typename Source, typename = enable_if_move_pathable<Source>> |
216 | | cmCMakePath& operator=(Source&& source) |
217 | 0 | { |
218 | 0 | this->Assign(std::forward<Source>(source)); |
219 | 0 | return *this; |
220 | 0 | } |
221 | | template <typename Source, typename = enable_if_pathable<Source>> |
222 | | cmCMakePath& operator=(Source const& source) |
223 | 0 | { |
224 | 0 | this->Assign(source); |
225 | 0 | return *this; |
226 | 0 | } Unexecuted instantiation: cmCMakePath& cmCMakePath::operator=<cm::filesystem::path, cmCMakePath&>(cm::filesystem::path const&) Unexecuted instantiation: cmCMakePath& cmCMakePath::operator=<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePath&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
227 | | #endif |
228 | | |
229 | | // Concatenation |
230 | | cmCMakePath& Append(cmCMakePath const& path) |
231 | 348 | { |
232 | 348 | return this->Append(path.Path); |
233 | 348 | } |
234 | | cmCMakePath& Append(cm::filesystem::path const& path) |
235 | 348 | { |
236 | 348 | this->Path /= path; |
237 | | // filesystem::path::append use preferred_separator ('\' on Windows) |
238 | | // so convert back to '/' |
239 | 348 | this->Path = this->Path.generic_string(); |
240 | 348 | return *this; |
241 | 348 | } |
242 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
243 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
244 | | // standard methods and templates use the same name. The template is selected |
245 | | // rather than the standard one regardless the arguments of the method. |
246 | | cmCMakePath& Append(std::string const& source) |
247 | | { |
248 | | return this->Append(cm::filesystem::path(source)); |
249 | | } |
250 | | cmCMakePath& Append(cm::string_view source) |
251 | | { |
252 | | return this->Append(cm::filesystem::path(source)); |
253 | | } |
254 | | cmCMakePath& Append(char const* source) |
255 | | { |
256 | | return this->Append(cm::filesystem::path(cm::string_view{ source })); |
257 | | } |
258 | | #else |
259 | | template <typename Source, typename = enable_if_pathable<Source>> |
260 | | cmCMakePath& Append(Source const& source) |
261 | 0 | { |
262 | 0 | return this->Append(cm::filesystem::path(source)); |
263 | 0 | } Unexecuted instantiation: cmCMakePath& cmCMakePath::Append<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePath&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: cmCMakePath& cmCMakePath::Append<char [21], cmCMakePath&>(char const (&) [21]) Unexecuted instantiation: cmCMakePath& cmCMakePath::Append<char [25], cmCMakePath&>(char const (&) [25]) Unexecuted instantiation: cmCMakePath& cmCMakePath::Append<char [19], cmCMakePath&>(char const (&) [19]) |
264 | | #endif |
265 | | |
266 | | cmCMakePath& operator/=(cmCMakePath const& path) |
267 | 348 | { |
268 | 348 | return this->Append(path); |
269 | 348 | } |
270 | | template <typename Source, typename = enable_if_pathable<Source>> |
271 | | cmCMakePath& operator/=(Source const& source) |
272 | 0 | { |
273 | 0 | return this->Append(source); |
274 | 0 | } |
275 | | |
276 | | cmCMakePath& Concat(cmCMakePath const& path) |
277 | 0 | { |
278 | 0 | this->Path += path.Path; |
279 | 0 | return *this; |
280 | 0 | } |
281 | | cmCMakePath& Concat(cm::string_view source) |
282 | 0 | { |
283 | 0 | this->Path.operator+=(std::string(source)); |
284 | 0 | return *this; |
285 | 0 | } |
286 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
287 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
288 | | // standard methods and templates use the same name. The template is selected |
289 | | // rather than the standard one regardless the arguments of the method. |
290 | | cmCMakePath& Concat(cm::filesystem::path const& source) |
291 | | { |
292 | | this->Path.operator+=(source); |
293 | | return *this; |
294 | | } |
295 | | cmCMakePath& Concat(std::string const& source) |
296 | | { |
297 | | this->Path.operator+=(source); |
298 | | return *this; |
299 | | } |
300 | | cmCMakePath& Concat(char const* source) |
301 | | { |
302 | | this->Path.operator+=(source); |
303 | | return *this; |
304 | | } |
305 | | #else |
306 | | template <typename Source, typename = enable_if_pathable<Source>> |
307 | | cmCMakePath& Concat(Source const& source) |
308 | 0 | { |
309 | 0 | this->Path.operator+=(source); |
310 | 0 | return *this; |
311 | 0 | } |
312 | | #endif |
313 | | |
314 | | cmCMakePath& operator+=(cmCMakePath const& path) |
315 | 0 | { |
316 | 0 | return this->Concat(path); |
317 | 0 | } |
318 | | template <typename Source, typename = enable_if_pathable<Source>> |
319 | | cmCMakePath& operator+=(Source const& source) |
320 | 0 | { |
321 | 0 | return this->Concat(source); |
322 | 0 | } |
323 | | |
324 | | // Manipulation |
325 | 0 | void Clear() noexcept { this->Path.clear(); } |
326 | | |
327 | | cmCMakePath& RemoveFileName() |
328 | 0 | { |
329 | 0 | this->Path.remove_filename(); |
330 | 0 | return *this; |
331 | 0 | } |
332 | | |
333 | | cmCMakePath& ReplaceFileName(cmCMakePath const& filename) |
334 | 0 | { |
335 | 0 | if (this->Path.has_filename()) { |
336 | 0 | this->Path.replace_filename(filename.Path); |
337 | 0 | } |
338 | 0 | return *this; |
339 | 0 | } |
340 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
341 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
342 | | // standard methods and templates use the same name. The template is selected |
343 | | // rather than the standard one regardless the arguments of the method. |
344 | | cmCMakePath& ReplaceFileName(cm::filesystem::path const& filename) |
345 | | { |
346 | | if (this->Path.has_filename()) { |
347 | | this->Path.replace_filename(filename); |
348 | | } |
349 | | return *this; |
350 | | } |
351 | | cmCMakePath& ReplaceFileName(std::string const& filename) |
352 | | { |
353 | | if (this->Path.has_filename()) { |
354 | | this->Path.replace_filename(filename); |
355 | | } |
356 | | return *this; |
357 | | } |
358 | | cmCMakePath& ReplaceFileName(cm::string_view filename) |
359 | | { |
360 | | if (this->Path.has_filename()) { |
361 | | this->Path.replace_filename(filename); |
362 | | } |
363 | | return *this; |
364 | | } |
365 | | #else |
366 | | template <typename Source, typename = enable_if_pathable<Source>> |
367 | | cmCMakePath& ReplaceFileName(Source const& filename) |
368 | 0 | { |
369 | 0 | if (this->Path.has_filename()) { |
370 | 0 | this->Path.replace_filename(filename); |
371 | 0 | } |
372 | 0 | return *this; |
373 | 0 | } |
374 | | #endif |
375 | | |
376 | | cmCMakePath& ReplaceExtension(cmCMakePath const& extension = cmCMakePath()) |
377 | 0 | { |
378 | 0 | this->Path.replace_extension(extension.Path); |
379 | 0 | return *this; |
380 | 0 | } |
381 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
382 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
383 | | // standard methods and templates use the same name. The template is selected |
384 | | // rather than the standard one regardless the arguments of the method. |
385 | | cmCMakePath& ReplaceExtension(cm::filesystem::path const& extension) |
386 | | { |
387 | | this->Path.replace_extension(extension); |
388 | | return *this; |
389 | | } |
390 | | cmCMakePath& ReplaceExtension(std::string const& extension) |
391 | | { |
392 | | this->Path.replace_extension(extension); |
393 | | return *this; |
394 | | } |
395 | | cmCMakePath& ReplaceExtension(cm::string_view const extension) |
396 | | { |
397 | | this->Path.replace_extension(extension); |
398 | | return *this; |
399 | | } |
400 | | #else |
401 | | template <typename Source, typename = enable_if_pathable<Source>> |
402 | | cmCMakePath& ReplaceExtension(Source const& extension) |
403 | 0 | { |
404 | 0 | this->Path.replace_extension(extension); |
405 | 0 | return *this; |
406 | 0 | } |
407 | | #endif |
408 | | |
409 | | cmCMakePath& ReplaceWideExtension( |
410 | | cmCMakePath const& extension = cmCMakePath()) |
411 | 0 | { |
412 | 0 | return this->ReplaceWideExtension( |
413 | 0 | static_cast<cm::string_view>(extension.Path.string())); |
414 | 0 | } |
415 | | cmCMakePath& ReplaceWideExtension(cm::filesystem::path const& extension) |
416 | 0 | { |
417 | 0 | return this->ReplaceWideExtension( |
418 | 0 | static_cast<cm::string_view>(extension.string())); |
419 | 0 | } |
420 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
421 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
422 | | // standard methods and templates use the same name. The template is selected |
423 | | // rather than the standard one regardless the arguments of the method. |
424 | | cmCMakePath& ReplaceWideExtension(std::string const& extension) |
425 | | { |
426 | | return this->ReplaceWideExtension(cm::string_view{ extension }); |
427 | | } |
428 | | #else |
429 | | template <typename Source, typename = enable_if_pathable<Source>> |
430 | | cmCMakePath& ReplaceWideExtension(Source const& extension) |
431 | | { |
432 | | return this->ReplaceWideExtension(extension); |
433 | | } |
434 | | #endif |
435 | | cmCMakePath& ReplaceWideExtension(cm::string_view extension); |
436 | | |
437 | | cmCMakePath& RemoveExtension() |
438 | 0 | { |
439 | 0 | if (this->Path.has_extension()) { |
440 | 0 | this->ReplaceExtension(cm::string_view("")); |
441 | 0 | } |
442 | 0 | return *this; |
443 | 0 | } |
444 | | |
445 | | cmCMakePath& RemoveWideExtension() |
446 | 0 | { |
447 | 0 | if (this->Path.has_extension()) { |
448 | 0 | this->ReplaceWideExtension(cm::string_view("")); |
449 | 0 | } |
450 | 0 | return *this; |
451 | 0 | } |
452 | | |
453 | 0 | void swap(cmCMakePath& other) noexcept { this->Path.swap(other.Path); } |
454 | | |
455 | | // Observers |
456 | 1.05k | std::string String() const { return this->Path.string(); } |
457 | 0 | std::wstring WString() const { return this->Path.wstring(); } |
458 | | |
459 | | string_type Native() const |
460 | 0 | { |
461 | 0 | string_type path; |
462 | 0 | this->GetNativePath(path); |
463 | 0 |
|
464 | 0 | return path; |
465 | 0 | } |
466 | | std::string NativeString() const |
467 | 0 | { |
468 | 0 | std::string path; |
469 | 0 | this->GetNativePath(path); |
470 | |
|
471 | 0 | return path; |
472 | 0 | } |
473 | | std::wstring NativeWString() const |
474 | 0 | { |
475 | 0 | std::wstring path; |
476 | 0 | this->GetNativePath(path); |
477 | 0 |
|
478 | 0 | return path; |
479 | 0 | } |
480 | 351 | std::string GenericString() const { return this->Path.generic_string(); } |
481 | 0 | std::wstring GenericWString() const { return this->Path.generic_wstring(); } |
482 | | |
483 | | // Decomposition |
484 | 351 | cmCMakePath GetRootName() const { return this->Path.root_name(); } |
485 | 351 | cmCMakePath GetRootDirectory() const { return this->Path.root_directory(); } |
486 | 351 | cmCMakePath GetRootPath() const { return this->Path.root_path(); } |
487 | 351 | cmCMakePath GetFileName() const { return this->Path.filename(); } |
488 | 351 | cmCMakePath GetExtension() const { return this->Path.extension(); } |
489 | | cmCMakePath GetWideExtension() const; |
490 | 351 | cmCMakePath GetStem() const { return this->Path.stem(); } |
491 | | cmCMakePath GetNarrowStem() const; |
492 | | |
493 | 351 | cmCMakePath GetRelativePath() const { return this->Path.relative_path(); } |
494 | 351 | cmCMakePath GetParentPath() const { return this->Path.parent_path(); } |
495 | | |
496 | | // Generation |
497 | | cmCMakePath Normal() const |
498 | 351 | { |
499 | 351 | auto path = this->Path.lexically_normal(); |
500 | | // filesystem::path:lexically_normal use preferred_separator ('\') on |
501 | | // Windows) so convert back to '/' |
502 | 351 | return path.generic_string(); |
503 | 351 | } |
504 | | |
505 | | cmCMakePath Relative(cmCMakePath const& base) const |
506 | 0 | { |
507 | 0 | return this->Relative(base.Path); |
508 | 0 | } |
509 | | cmCMakePath Relative(cm::filesystem::path const& base) const |
510 | 0 | { |
511 | 0 | auto path = this->Path.lexically_relative(base); |
512 | | // filesystem::path:lexically_relative use preferred_separator ('\') on |
513 | | // Windows) so convert back to '/' |
514 | 0 | return path.generic_string(); |
515 | 0 | } |
516 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
517 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
518 | | // standard methods and templates use the same name. The template is selected |
519 | | // rather than the standard one regardless the arguments of the method. |
520 | | cmCMakePath Relative(std::string const& base) const |
521 | | { |
522 | | return this->Relative(cm::filesystem::path(base)); |
523 | | } |
524 | | cmCMakePath Relative(cm::string_view base) const |
525 | | { |
526 | | return this->Relative(cm::filesystem::path(base)); |
527 | | } |
528 | | #else |
529 | | template <typename Source, typename = enable_if_pathable<Source>> |
530 | | cmCMakePath Relative(Source const& base) const |
531 | 0 | { |
532 | 0 | return this->Relative(cm::filesystem::path(base)); |
533 | 0 | } |
534 | | #endif |
535 | | cmCMakePath Proximate(cmCMakePath const& base) const |
536 | 0 | { |
537 | 0 | return this->Proximate(base.Path); |
538 | 0 | } |
539 | | cmCMakePath Proximate(cm::filesystem::path const& base) const |
540 | 0 | { |
541 | 0 | auto path = this->Path.lexically_proximate(base); |
542 | 0 | // filesystem::path::lexically_proximate use preferred_separator ('\') on |
543 | 0 | // Windows) so convert back to '/' |
544 | 0 | return path.generic_string(); |
545 | 0 | } |
546 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
547 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
548 | | // standard methods and templates use the same name. The template is selected |
549 | | // rather than the standard one regardless the arguments of the method. |
550 | | cmCMakePath Proximate(std::string const& base) const |
551 | | { |
552 | | return this->Proximate(cm::filesystem::path(base)); |
553 | | } |
554 | | cmCMakePath Proximate(cm::string_view base) const |
555 | | { |
556 | | return this->Proximate(cm::filesystem::path(base)); |
557 | | } |
558 | | #else |
559 | | template <typename Source, typename = enable_if_pathable<Source>> |
560 | | cmCMakePath Proximate(Source const& base) const |
561 | | { |
562 | | return this->Proximate(cm::filesystem::path(base)); |
563 | | } |
564 | | #endif |
565 | | |
566 | | cmCMakePath Absolute(cmCMakePath const& base) const |
567 | 0 | { |
568 | 0 | return this->Absolute(base.Path); |
569 | 0 | } |
570 | | #if defined(__SUNPRO_CC) && defined(__sparc) |
571 | | // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when |
572 | | // standard methods and templates use the same name. The template is selected |
573 | | // rather than the standard one regardless the arguments of the method. |
574 | | cmCMakePath Absolute(std::string const& base) const |
575 | | { |
576 | | return this->Absolute(cm::filesystem::path(base)); |
577 | | } |
578 | | cmCMakePath Absolute(cm::string_view base) const |
579 | | { |
580 | | return this->Absolute(cm::filesystem::path(base)); |
581 | | } |
582 | | #else |
583 | | template <typename Source, typename = enable_if_pathable<Source>> |
584 | | cmCMakePath Absolute(Source const& base) const |
585 | 0 | { |
586 | 0 | return this->Absolute(cm::filesystem::path(base)); |
587 | 0 | } |
588 | | #endif |
589 | | cmCMakePath Absolute(cm::filesystem::path const& base) const; |
590 | | |
591 | | // Comparison |
592 | | int Compare(cmCMakePath const& path) const noexcept |
593 | 348 | { |
594 | 348 | return this->Path.compare(path.Path); |
595 | 348 | } |
596 | | |
597 | | // Query |
598 | 351 | bool IsEmpty() const noexcept { return this->Path.empty(); } |
599 | | |
600 | 351 | bool HasRootPath() const { return this->Path.has_root_path(); } |
601 | 351 | bool HasRootName() const { return this->Path.has_root_name(); } |
602 | 351 | bool HasRootDirectory() const { return this->Path.has_root_directory(); } |
603 | 351 | bool HasRelativePath() const { return this->Path.has_relative_path(); } |
604 | 351 | bool HasParentPath() const { return this->Path.has_parent_path(); } |
605 | 351 | bool HasFileName() const { return this->Path.has_filename(); } |
606 | 351 | bool HasStem() const { return this->Path.has_stem(); } |
607 | 351 | bool HasExtension() const { return this->Path.has_extension(); } |
608 | | |
609 | 351 | bool IsAbsolute() const { return this->Path.is_absolute(); } |
610 | 351 | bool IsRelative() const { return this->Path.is_relative(); } |
611 | | bool IsPrefix(cmCMakePath const& path) const; |
612 | | |
613 | | // Iterators |
614 | | // ========= |
615 | | inline iterator begin() const; |
616 | | inline iterator end() const; |
617 | | |
618 | | // Non-members |
619 | | // =========== |
620 | | friend bool operator==(cmCMakePath const& lhs, |
621 | | cmCMakePath const& rhs) noexcept |
622 | 348 | { |
623 | 348 | return lhs.Compare(rhs) == 0; |
624 | 348 | } |
625 | | friend bool operator!=(cmCMakePath const& lhs, |
626 | | cmCMakePath const& rhs) noexcept |
627 | 0 | { |
628 | 0 | return lhs.Compare(rhs) != 0; |
629 | 0 | } |
630 | | |
631 | | friend cmCMakePath operator/(cmCMakePath const& lhs, cmCMakePath const& rhs) |
632 | 348 | { |
633 | 348 | cmCMakePath result(lhs); |
634 | 348 | result /= rhs; |
635 | | |
636 | 348 | return result; |
637 | 348 | } |
638 | | |
639 | | private: |
640 | | friend std::size_t hash_value(cmCMakePath const& path) noexcept; |
641 | | |
642 | | static std::string FormatPath(std::string path, format fmt = generic_format); |
643 | | static std::string FormatPath(cm::string_view path, |
644 | | format fmt = generic_format) |
645 | 0 | { |
646 | 0 | return FormatPath(std::string(path), fmt); |
647 | 0 | } |
648 | | |
649 | | void GetNativePath(std::string& path) const; |
650 | | void GetNativePath(std::wstring& path) const; |
651 | | |
652 | | cm::filesystem::path Path; |
653 | | }; |
654 | | |
655 | | class cmCMakePath::iterator |
656 | | { |
657 | | public: |
658 | | using iterator_category = cm::filesystem::path::iterator::iterator_category; |
659 | | |
660 | | using value_type = cmCMakePath; |
661 | | using difference_type = cm::filesystem::path::iterator::difference_type; |
662 | | using pointer = cmCMakePath const*; |
663 | | using reference = cmCMakePath const&; |
664 | | |
665 | | iterator() = default; |
666 | | |
667 | 0 | iterator(iterator const& other) = default; |
668 | | |
669 | 0 | ~iterator() = default; |
670 | | |
671 | | iterator& operator=(iterator const& other) |
672 | 0 | { |
673 | 0 | if (this != &other) { |
674 | 0 | this->Iterator = other.Iterator; |
675 | 0 | this->Path = other.Path; |
676 | 0 | this->PathElement = other.PathElement; |
677 | 0 | } |
678 | 0 |
|
679 | 0 | return *this; |
680 | 0 | } |
681 | | |
682 | 0 | reference operator*() const { return this->PathElement; } |
683 | | |
684 | 0 | pointer operator->() const { return &this->PathElement; } |
685 | | |
686 | | iterator& operator++() |
687 | 0 | { |
688 | 0 | ++this->Iterator; |
689 | 0 | if (this->Path && this->Iterator != this->Path->Path.end()) { |
690 | 0 | this->PathElement = *this->Iterator; |
691 | 0 | } |
692 | |
|
693 | 0 | return *this; |
694 | 0 | } |
695 | | |
696 | | iterator operator++(int) |
697 | 0 | { |
698 | 0 | iterator it(*this); |
699 | 0 | this->operator++(); |
700 | 0 | return it; |
701 | 0 | } |
702 | | |
703 | | iterator& operator--() |
704 | 0 | { |
705 | 0 | --this->Iterator; |
706 | 0 | if (this->Path && this->Iterator != this->Path->Path.end()) { |
707 | 0 | this->PathElement = *this->Iterator; |
708 | 0 | } |
709 | 0 |
|
710 | 0 | return *this; |
711 | 0 | } |
712 | | |
713 | | iterator operator--(int) |
714 | 0 | { |
715 | 0 | iterator it(*this); |
716 | 0 | this->operator--(); |
717 | 0 | return it; |
718 | 0 | } |
719 | | |
720 | | private: |
721 | | friend class cmCMakePath; |
722 | | friend bool operator==(iterator const&, iterator const&); |
723 | | |
724 | | iterator(cmCMakePath const* path, cm::filesystem::path::iterator const& it) |
725 | 0 | : Iterator(it) |
726 | 0 | , Path(path) |
727 | 0 | { |
728 | 0 | if (this->Path && this->Iterator != this->Path->Path.end()) { |
729 | 0 | this->PathElement = *this->Iterator; |
730 | 0 | } |
731 | 0 | } |
732 | | |
733 | | cm::filesystem::path::iterator Iterator; |
734 | | cmCMakePath const* Path = nullptr; |
735 | | cmCMakePath PathElement; |
736 | | }; |
737 | | |
738 | | inline cmCMakePath::iterator cmCMakePath::begin() const |
739 | 0 | { |
740 | 0 | return iterator(this, this->Path.begin()); |
741 | 0 | } |
742 | | inline cmCMakePath::iterator cmCMakePath::end() const |
743 | 0 | { |
744 | 0 | return iterator(this, this->Path.end()); |
745 | 0 | } |
746 | | |
747 | | // Non-member functions |
748 | | // ==================== |
749 | | inline bool operator==(cmCMakePath::iterator const& lhs, |
750 | | cmCMakePath::iterator const& rhs) |
751 | 0 | { |
752 | 0 | return lhs.Path == rhs.Path && lhs.Path && lhs.Iterator == rhs.Iterator; |
753 | 0 | } |
754 | | |
755 | | inline bool operator!=(cmCMakePath::iterator const& lhs, |
756 | | cmCMakePath::iterator const& rhs) |
757 | 0 | { |
758 | 0 | return !(lhs == rhs); |
759 | 0 | } |
760 | | |
761 | | inline void swap(cmCMakePath& lhs, cmCMakePath& rhs) noexcept |
762 | 0 | { |
763 | 0 | lhs.swap(rhs); |
764 | 0 | } |
765 | | |
766 | | inline std::size_t hash_value(cmCMakePath const& path) noexcept |
767 | 0 | { |
768 | 0 | return cm::filesystem::hash_value(path.Path); |
769 | 0 | } |