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