1 | //===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file declares the llvm::sys::path namespace. It is designed after |
10 | // TR2/boost filesystem (v3), but modified to remove exception handling and the |
11 | // path class. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_SUPPORT_PATH_H |
16 | #define LLVM_SUPPORT_PATH_H |
17 | |
18 | #include "llvm/ADT/Twine.h" |
19 | #include "llvm/ADT/iterator.h" |
20 | #include "llvm/Support/DataTypes.h" |
21 | #include <iterator> |
22 | |
23 | namespace llvm { |
24 | namespace sys { |
25 | namespace path { |
26 | |
27 | enum class Style { |
28 | native, |
29 | posix, |
30 | windows_slash, |
31 | windows_backslash, |
32 | windows = windows_backslash, // deprecated |
33 | }; |
34 | |
35 | /// Check if \p S uses POSIX path rules. |
36 | constexpr bool is_style_posix(Style S) { |
37 | if (S == Style::posix) |
38 | return true; |
39 | if (S != Style::native) |
40 | return false; |
41 | #if defined(_WIN32) |
42 | return false; |
43 | #else |
44 | return true; |
45 | #endif |
46 | } |
47 | |
48 | /// Check if \p S uses Windows path rules. |
49 | constexpr bool is_style_windows(Style S) { return !is_style_posix(S); } |
50 | |
51 | /// @name Lexical Component Iterator |
52 | /// @{ |
53 | |
54 | /// Path iterator. |
55 | /// |
56 | /// This is an input iterator that iterates over the individual components in |
57 | /// \a path. The traversal order is as follows: |
58 | /// * The root-name element, if present. |
59 | /// * The root-directory element, if present. |
60 | /// * Each successive filename element, if present. |
61 | /// * Dot, if one or more trailing non-root slash characters are present. |
62 | /// Traversing backwards is possible with \a reverse_iterator |
63 | /// |
64 | /// Iteration examples. Each component is separated by ',': |
65 | /// @code |
66 | /// / => / |
67 | /// /foo => /,foo |
68 | /// foo/ => foo,. |
69 | /// /foo/bar => /,foo,bar |
70 | /// ../ => ..,. |
71 | /// C:\foo\bar => C:,\,foo,bar |
72 | /// @endcode |
73 | class const_iterator |
74 | : public iterator_facade_base<const_iterator, std::input_iterator_tag, |
75 | const StringRef> { |
76 | StringRef Path; ///< The entire path. |
77 | StringRef Component; ///< The current component. Not necessarily in Path. |
78 | size_t Position = 0; ///< The iterators current position within Path. |
79 | Style S = Style::native; ///< The path style to use. |
80 | |
81 | // An end iterator has Position = Path.size() + 1. |
82 | friend const_iterator begin(StringRef path, Style style); |
83 | friend const_iterator end(StringRef path); |
84 | |
85 | public: |
86 | reference operator*() const { return Component; } |
87 | const_iterator &operator++(); // preincrement |
88 | bool operator==(const const_iterator &RHS) const; |
89 | |
90 | /// Difference in bytes between this and RHS. |
91 | ptrdiff_t operator-(const const_iterator &RHS) const; |
92 | }; |
93 | |
94 | /// Reverse path iterator. |
95 | /// |
96 | /// This is an input iterator that iterates over the individual components in |
97 | /// \a path in reverse order. The traversal order is exactly reversed from that |
98 | /// of \a const_iterator |
99 | class reverse_iterator |
100 | : public iterator_facade_base<reverse_iterator, std::input_iterator_tag, |
101 | const StringRef> { |
102 | StringRef Path; ///< The entire path. |
103 | StringRef Component; ///< The current component. Not necessarily in Path. |
104 | size_t Position = 0; ///< The iterators current position within Path. |
105 | Style S = Style::native; ///< The path style to use. |
106 | |
107 | friend reverse_iterator rbegin(StringRef path, Style style); |
108 | friend reverse_iterator rend(StringRef path); |
109 | |
110 | public: |
111 | reference operator*() const { return Component; } |
112 | reverse_iterator &operator++(); // preincrement |
113 | bool operator==(const reverse_iterator &RHS) const; |
114 | |
115 | /// Difference in bytes between this and RHS. |
116 | ptrdiff_t operator-(const reverse_iterator &RHS) const; |
117 | }; |
118 | |
119 | /// Get begin iterator over \a path. |
120 | /// @param path Input path. |
121 | /// @returns Iterator initialized with the first component of \a path. |
122 | const_iterator begin(StringRef path, Style style = Style::native); |
123 | |
124 | /// Get end iterator over \a path. |
125 | /// @param path Input path. |
126 | /// @returns Iterator initialized to the end of \a path. |
127 | const_iterator end(StringRef path); |
128 | |
129 | /// Get reverse begin iterator over \a path. |
130 | /// @param path Input path. |
131 | /// @returns Iterator initialized with the first reverse component of \a path. |
132 | reverse_iterator rbegin(StringRef path, Style style = Style::native); |
133 | |
134 | /// Get reverse end iterator over \a path. |
135 | /// @param path Input path. |
136 | /// @returns Iterator initialized to the reverse end of \a path. |
137 | reverse_iterator rend(StringRef path); |
138 | |
139 | /// @} |
140 | /// @name Lexical Modifiers |
141 | /// @{ |
142 | |
143 | /// Remove the last component from \a path unless it is the root dir. |
144 | /// |
145 | /// Similar to the POSIX "dirname" utility. |
146 | /// |
147 | /// @code |
148 | /// directory/filename.cpp => directory/ |
149 | /// directory/ => directory |
150 | /// filename.cpp => <empty> |
151 | /// / => / |
152 | /// @endcode |
153 | /// |
154 | /// @param path A path that is modified to not have a file component. |
155 | void remove_filename(SmallVectorImpl<char> &path, Style style = Style::native); |
156 | |
157 | /// Replace the file extension of \a path with \a extension. |
158 | /// |
159 | /// @code |
160 | /// ./filename.cpp => ./filename.extension |
161 | /// ./filename => ./filename.extension |
162 | /// ./ => ./.extension |
163 | /// @endcode |
164 | /// |
165 | /// @param path A path that has its extension replaced with \a extension. |
166 | /// @param extension The extension to be added. It may be empty. It may also |
167 | /// optionally start with a '.', if it does not, one will be |
168 | /// prepended. |
169 | void replace_extension(SmallVectorImpl<char> &path, const Twine &extension, |
170 | Style style = Style::native); |
171 | |
172 | /// Replace matching path prefix with another path. |
173 | /// |
174 | /// @code |
175 | /// /foo, /old, /new => /foo |
176 | /// /old, /old, /new => /new |
177 | /// /old, /old/, /new => /old |
178 | /// /old/foo, /old, /new => /new/foo |
179 | /// /old/foo, /old/, /new => /new/foo |
180 | /// /old/foo, /old/, /new/ => /new/foo |
181 | /// /oldfoo, /old, /new => /oldfoo |
182 | /// /foo, <empty>, /new => /new/foo |
183 | /// /foo, <empty>, new => new/foo |
184 | /// /old/foo, /old, <empty> => /foo |
185 | /// @endcode |
186 | /// |
187 | /// @param Path If \a Path starts with \a OldPrefix modify to instead |
188 | /// start with \a NewPrefix. |
189 | /// @param OldPrefix The path prefix to strip from \a Path. |
190 | /// @param NewPrefix The path prefix to replace \a NewPrefix with. |
191 | /// @param style The style used to match the prefix. Exact match using |
192 | /// Posix style, case/separator insensitive match for Windows style. |
193 | /// @result true if \a Path begins with OldPrefix |
194 | bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix, |
195 | StringRef NewPrefix, |
196 | Style style = Style::native); |
197 | |
198 | /// Remove redundant leading "./" pieces and consecutive separators. |
199 | /// |
200 | /// @param path Input path. |
201 | /// @result The cleaned-up \a path. |
202 | StringRef remove_leading_dotslash(StringRef path, Style style = Style::native); |
203 | |
204 | /// In-place remove any './' and optionally '../' components from a path. |
205 | /// |
206 | /// @param path processed path |
207 | /// @param remove_dot_dot specify if '../' (except for leading "../") should be |
208 | /// removed |
209 | /// @result True if path was changed |
210 | bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false, |
211 | Style style = Style::native); |
212 | |
213 | /// Append to path. |
214 | /// |
215 | /// @code |
216 | /// /foo + bar/f => /foo/bar/f |
217 | /// /foo/ + bar/f => /foo/bar/f |
218 | /// foo + bar/f => foo/bar/f |
219 | /// @endcode |
220 | /// |
221 | /// @param path Set to \a path + \a component. |
222 | /// @param a The component to be appended to \a path. |
223 | void append(SmallVectorImpl<char> &path, const Twine &a, |
224 | const Twine &b = "" , |
225 | const Twine &c = "" , |
226 | const Twine &d = "" ); |
227 | |
228 | void append(SmallVectorImpl<char> &path, Style style, const Twine &a, |
229 | const Twine &b = "" , const Twine &c = "" , const Twine &d = "" ); |
230 | |
231 | /// Append to path. |
232 | /// |
233 | /// @code |
234 | /// /foo + [bar,f] => /foo/bar/f |
235 | /// /foo/ + [bar,f] => /foo/bar/f |
236 | /// foo + [bar,f] => foo/bar/f |
237 | /// @endcode |
238 | /// |
239 | /// @param path Set to \a path + [\a begin, \a end). |
240 | /// @param begin Start of components to append. |
241 | /// @param end One past the end of components to append. |
242 | void append(SmallVectorImpl<char> &path, const_iterator begin, |
243 | const_iterator end, Style style = Style::native); |
244 | |
245 | /// @} |
246 | /// @name Transforms (or some other better name) |
247 | /// @{ |
248 | |
249 | /// Convert path to the native form. This is used to give paths to users and |
250 | /// operating system calls in the platform's normal way. For example, on Windows |
251 | /// all '/' are converted to '\'. On Unix, it converts all '\' to '/'. |
252 | /// |
253 | /// @param path A path that is transformed to native format. |
254 | /// @param result Holds the result of the transformation. |
255 | void native(const Twine &path, SmallVectorImpl<char> &result, |
256 | Style style = Style::native); |
257 | |
258 | /// Convert path to the native form in place. This is used to give paths to |
259 | /// users and operating system calls in the platform's normal way. For example, |
260 | /// on Windows all '/' are converted to '\'. |
261 | /// |
262 | /// @param path A path that is transformed to native format. |
263 | void native(SmallVectorImpl<char> &path, Style style = Style::native); |
264 | |
265 | /// For Windows path styles, convert path to use the preferred path separators. |
266 | /// For other styles, do nothing. |
267 | /// |
268 | /// @param path A path that is transformed to preferred format. |
269 | inline void make_preferred(SmallVectorImpl<char> &path, |
270 | Style style = Style::native) { |
271 | if (!is_style_windows(S: style)) |
272 | return; |
273 | native(path, style); |
274 | } |
275 | |
276 | /// Replaces backslashes with slashes if Windows. |
277 | /// |
278 | /// @param path processed path |
279 | /// @result The result of replacing backslashes with forward slashes if Windows. |
280 | /// On Unix, this function is a no-op because backslashes are valid path |
281 | /// chracters. |
282 | std::string convert_to_slash(StringRef path, Style style = Style::native); |
283 | |
284 | /// @} |
285 | /// @name Lexical Observers |
286 | /// @{ |
287 | |
288 | /// Get root name. |
289 | /// |
290 | /// @code |
291 | /// //net/hello => //net |
292 | /// c:/hello => c: (on Windows, on other platforms nothing) |
293 | /// /hello => <empty> |
294 | /// @endcode |
295 | /// |
296 | /// @param path Input path. |
297 | /// @result The root name of \a path if it has one, otherwise "". |
298 | StringRef root_name(StringRef path, Style style = Style::native); |
299 | |
300 | /// Get root directory. |
301 | /// |
302 | /// @code |
303 | /// /goo/hello => / |
304 | /// c:/hello => / |
305 | /// d/file.txt => <empty> |
306 | /// @endcode |
307 | /// |
308 | /// @param path Input path. |
309 | /// @result The root directory of \a path if it has one, otherwise |
310 | /// "". |
311 | StringRef root_directory(StringRef path, Style style = Style::native); |
312 | |
313 | /// Get root path. |
314 | /// |
315 | /// Equivalent to root_name + root_directory. |
316 | /// |
317 | /// @param path Input path. |
318 | /// @result The root path of \a path if it has one, otherwise "". |
319 | StringRef root_path(StringRef path, Style style = Style::native); |
320 | |
321 | /// Get relative path. |
322 | /// |
323 | /// @code |
324 | /// C:\hello\world => hello\world |
325 | /// foo/bar => foo/bar |
326 | /// /foo/bar => foo/bar |
327 | /// @endcode |
328 | /// |
329 | /// @param path Input path. |
330 | /// @result The path starting after root_path if one exists, otherwise "". |
331 | StringRef relative_path(StringRef path, Style style = Style::native); |
332 | |
333 | /// Get parent path. |
334 | /// |
335 | /// @code |
336 | /// / => <empty> |
337 | /// /foo => / |
338 | /// foo/../bar => foo/.. |
339 | /// @endcode |
340 | /// |
341 | /// @param path Input path. |
342 | /// @result The parent path of \a path if one exists, otherwise "". |
343 | StringRef parent_path(StringRef path, Style style = Style::native); |
344 | |
345 | /// Get filename. |
346 | /// |
347 | /// @code |
348 | /// /foo.txt => foo.txt |
349 | /// . => . |
350 | /// .. => .. |
351 | /// / => / |
352 | /// @endcode |
353 | /// |
354 | /// @param path Input path. |
355 | /// @result The filename part of \a path. This is defined as the last component |
356 | /// of \a path. Similar to the POSIX "basename" utility. |
357 | StringRef filename(StringRef path, Style style = Style::native); |
358 | |
359 | /// Get stem. |
360 | /// |
361 | /// If filename contains a dot but not solely one or two dots, result is the |
362 | /// substring of filename ending at (but not including) the last dot. Otherwise |
363 | /// it is filename. |
364 | /// |
365 | /// @code |
366 | /// /foo/bar.txt => bar |
367 | /// /foo/bar => bar |
368 | /// /foo/.txt => <empty> |
369 | /// /foo/. => . |
370 | /// /foo/.. => .. |
371 | /// @endcode |
372 | /// |
373 | /// @param path Input path. |
374 | /// @result The stem of \a path. |
375 | StringRef stem(StringRef path, Style style = Style::native); |
376 | |
377 | /// Get extension. |
378 | /// |
379 | /// If filename contains a dot but not solely one or two dots, result is the |
380 | /// substring of filename starting at (and including) the last dot, and ending |
381 | /// at the end of \a path. Otherwise "". |
382 | /// |
383 | /// @code |
384 | /// /foo/bar.txt => .txt |
385 | /// /foo/bar => <empty> |
386 | /// /foo/.txt => .txt |
387 | /// @endcode |
388 | /// |
389 | /// @param path Input path. |
390 | /// @result The extension of \a path. |
391 | StringRef extension(StringRef path, Style style = Style::native); |
392 | |
393 | /// Check whether the given char is a path separator on the host OS. |
394 | /// |
395 | /// @param value a character |
396 | /// @result true if \a value is a path separator character on the host OS |
397 | bool is_separator(char value, Style style = Style::native); |
398 | |
399 | /// Return the preferred separator for this platform. |
400 | /// |
401 | /// @result StringRef of the preferred separator, null-terminated. |
402 | StringRef get_separator(Style style = Style::native); |
403 | |
404 | /// Get the typical temporary directory for the system, e.g., |
405 | /// "/var/tmp" or "C:/TEMP" |
406 | /// |
407 | /// @param erasedOnReboot Whether to favor a path that is erased on reboot |
408 | /// rather than one that potentially persists longer. This parameter will be |
409 | /// ignored if the user or system has set the typical environment variable |
410 | /// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory. |
411 | /// |
412 | /// @param result Holds the resulting path name. |
413 | void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result); |
414 | |
415 | /// Get the user's home directory. |
416 | /// |
417 | /// @param result Holds the resulting path name. |
418 | /// @result True if a home directory is set, false otherwise. |
419 | bool home_directory(SmallVectorImpl<char> &result); |
420 | |
421 | /// Get the directory where packages should read user-specific configurations. |
422 | /// e.g. $XDG_CONFIG_HOME. |
423 | /// |
424 | /// @param result Holds the resulting path name. |
425 | /// @result True if the appropriate path was determined, it need not exist. |
426 | bool user_config_directory(SmallVectorImpl<char> &result); |
427 | |
428 | /// Get the directory where installed packages should put their |
429 | /// machine-local cache, e.g. $XDG_CACHE_HOME. |
430 | /// |
431 | /// @param result Holds the resulting path name. |
432 | /// @result True if the appropriate path was determined, it need not exist. |
433 | bool cache_directory(SmallVectorImpl<char> &result); |
434 | |
435 | /// Has root name? |
436 | /// |
437 | /// root_name != "" |
438 | /// |
439 | /// @param path Input path. |
440 | /// @result True if the path has a root name, false otherwise. |
441 | bool has_root_name(const Twine &path, Style style = Style::native); |
442 | |
443 | /// Has root directory? |
444 | /// |
445 | /// root_directory != "" |
446 | /// |
447 | /// @param path Input path. |
448 | /// @result True if the path has a root directory, false otherwise. |
449 | bool has_root_directory(const Twine &path, Style style = Style::native); |
450 | |
451 | /// Has root path? |
452 | /// |
453 | /// root_path != "" |
454 | /// |
455 | /// @param path Input path. |
456 | /// @result True if the path has a root path, false otherwise. |
457 | bool has_root_path(const Twine &path, Style style = Style::native); |
458 | |
459 | /// Has relative path? |
460 | /// |
461 | /// relative_path != "" |
462 | /// |
463 | /// @param path Input path. |
464 | /// @result True if the path has a relative path, false otherwise. |
465 | bool has_relative_path(const Twine &path, Style style = Style::native); |
466 | |
467 | /// Has parent path? |
468 | /// |
469 | /// parent_path != "" |
470 | /// |
471 | /// @param path Input path. |
472 | /// @result True if the path has a parent path, false otherwise. |
473 | bool has_parent_path(const Twine &path, Style style = Style::native); |
474 | |
475 | /// Has filename? |
476 | /// |
477 | /// filename != "" |
478 | /// |
479 | /// @param path Input path. |
480 | /// @result True if the path has a filename, false otherwise. |
481 | bool has_filename(const Twine &path, Style style = Style::native); |
482 | |
483 | /// Has stem? |
484 | /// |
485 | /// stem != "" |
486 | /// |
487 | /// @param path Input path. |
488 | /// @result True if the path has a stem, false otherwise. |
489 | bool has_stem(const Twine &path, Style style = Style::native); |
490 | |
491 | /// Has extension? |
492 | /// |
493 | /// extension != "" |
494 | /// |
495 | /// @param path Input path. |
496 | /// @result True if the path has a extension, false otherwise. |
497 | bool has_extension(const Twine &path, Style style = Style::native); |
498 | |
499 | /// Is path absolute? |
500 | /// |
501 | /// According to cppreference.com, C++17 states: "An absolute path is a path |
502 | /// that unambiguously identifies the location of a file without reference to |
503 | /// an additional starting location." |
504 | /// |
505 | /// In other words, the rules are: |
506 | /// 1) POSIX style paths with nonempty root directory are absolute. |
507 | /// 2) Windows style paths with nonempty root name and root directory are |
508 | /// absolute. |
509 | /// 3) No other paths are absolute. |
510 | /// |
511 | /// \see has_root_name |
512 | /// \see has_root_directory |
513 | /// |
514 | /// @param path Input path. |
515 | /// @result True if the path is absolute, false if it is not. |
516 | bool is_absolute(const Twine &path, Style style = Style::native); |
517 | |
518 | /// Is path absolute using GNU rules? |
519 | /// |
520 | /// GNU rules are: |
521 | /// 1) Paths starting with a path separator are absolute. |
522 | /// 2) Windows style paths are also absolute if they start with a character |
523 | /// followed by ':'. |
524 | /// 3) No other paths are absolute. |
525 | /// |
526 | /// On Windows style the path "C:\Users\Default" has "C:" as root name and "\" |
527 | /// as root directory. |
528 | /// |
529 | /// Hence "C:" on Windows is absolute under GNU rules and not absolute under |
530 | /// C++17 because it has no root directory. Likewise "/" and "\" on Windows are |
531 | /// absolute under GNU and are not absolute under C++17 due to empty root name. |
532 | /// |
533 | /// \see has_root_name |
534 | /// \see has_root_directory |
535 | /// |
536 | /// @param path Input path. |
537 | /// @param style The style of \p path (e.g. Windows or POSIX). "native" style |
538 | /// means to derive the style from the host. |
539 | /// @result True if the path is absolute following GNU rules, false if it is |
540 | /// not. |
541 | bool is_absolute_gnu(const Twine &path, Style style = Style::native); |
542 | |
543 | /// Is path relative? |
544 | /// |
545 | /// @param path Input path. |
546 | /// @result True if the path is relative, false if it is not. |
547 | bool is_relative(const Twine &path, Style style = Style::native); |
548 | |
549 | } // end namespace path |
550 | } // end namespace sys |
551 | } // end namespace llvm |
552 | |
553 | #endif |
554 | |