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