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