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