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