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(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