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