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