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