PathV2.h revision ad8a14f24eb3daee61c8076ff6e5a8135f4dd124
1//===- llvm/Support/PathV2.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// All functions return an error_code and their actual work via the last out 15// argument. The out argument is defined if and only if errc::success is 16// returned. A function may return any error code in the generic or system 17// category. However, they shall be equivalent to any error conditions listed 18// in each functions respective documentation if the condition applies. [ note: 19// this does not guarantee that error_code will be in the set of explicitly 20// listed codes, but it does guarantee that if any of the explicitly listed 21// errors occur, the correct error_code will be used ]. All functions may 22// return errc::not_enough_memory if there is not enough memory to complete the 23// operation. 24// 25//===----------------------------------------------------------------------===// 26 27#ifndef LLVM_SUPPORT_PATHV2_H 28#define LLVM_SUPPORT_PATHV2_H 29 30#include "llvm/ADT/SmallString.h" 31#include "llvm/ADT/Twine.h" 32#include "llvm/Support/DataTypes.h" 33#include "llvm/Support/system_error.h" 34#include <iterator> 35 36namespace llvm { 37namespace sys { 38namespace path { 39 40/// @name Lexical Component Iterator 41/// @{ 42 43/// @brief Path iterator. 44/// 45/// This is a bidirectional iterator that iterates over the individual 46/// components in \a path. The forward traversal order is as follows: 47/// * The root-name element, if present. 48/// * The root-directory element, if present. 49/// * Each successive filename element, if present. 50/// * Dot, if one or more trailing non-root slash characters are present. 51/// The backwards traversal order is the reverse of forward traversal. 52/// 53/// Iteration examples. Each component is separated by ',': 54/// / => / 55/// /foo => /,foo 56/// foo/ => foo,. 57/// /foo/bar => /,foo,bar 58/// ../ => ..,. 59/// C:\foo\bar => C:,/,foo,bar 60/// 61class const_iterator { 62 StringRef Path; //< The entire path. 63 StringRef Component; //< The current component. Not necessarily in Path. 64 size_t Position; //< The iterators current position within Path. 65 66 // An end iterator has Position = Path.size() + 1. 67 friend const_iterator begin(const StringRef &path); 68 friend const_iterator end(const StringRef &path); 69 70public: 71 typedef const StringRef value_type; 72 typedef ptrdiff_t difference_type; 73 typedef value_type &reference; 74 typedef value_type *pointer; 75 typedef std::bidirectional_iterator_tag iterator_category; 76 77 reference operator*() const { return Component; } 78 pointer operator->() const { return &Component; } 79 const_iterator &operator++(); // preincrement 80 const_iterator &operator++(int); // postincrement 81 const_iterator &operator--(); // predecrement 82 const_iterator &operator--(int); // postdecrement 83 bool operator==(const const_iterator &RHS) const; 84 bool operator!=(const const_iterator &RHS) const; 85 86 /// @brief Difference in bytes between this and RHS. 87 ptrdiff_t operator-(const const_iterator &RHS) const; 88}; 89 90typedef std::reverse_iterator<const_iterator> reverse_iterator; 91 92/// @brief Get begin iterator over \a path. 93/// @param path Input path. 94/// @returns Iterator initialized with the first component of \a path. 95const_iterator begin(const StringRef &path); 96 97/// @brief Get end iterator over \a path. 98/// @param path Input path. 99/// @returns Iterator initialized to the end of \a path. 100const_iterator end(const StringRef &path); 101 102/// @brief Get reverse begin iterator over \a path. 103/// @param path Input path. 104/// @returns Iterator initialized with the first reverse component of \a path. 105inline reverse_iterator rbegin(const StringRef &path) { 106 return reverse_iterator(end(path)); 107} 108 109/// @brief Get reverse end iterator over \a path. 110/// @param path Input path. 111/// @returns Iterator initialized to the reverse end of \a path. 112inline reverse_iterator rend(const StringRef &path) { 113 return reverse_iterator(begin(path)); 114} 115 116/// @} 117/// @name Lexical Modifiers 118/// @{ 119 120/// @brief Make \a path an absolute path. 121/// 122/// Makes \a path absolute using the current directory if it is not already. An 123/// empty \a path will result in the current directory. 124/// 125/// /absolute/path => /absolute/path 126/// relative/../path => <current-directory>/relative/../path 127/// 128/// @param path A path that is modified to be an absolute path. 129/// @returns errc::success if \a path has been made absolute, otherwise a 130/// platform specific error_code. 131error_code make_absolute(SmallVectorImpl<char> &path); 132 133/// @brief Remove the last component from \a path unless it is the root dir. 134/// 135/// directory/filename.cpp => directory/ 136/// directory/ => directory 137/// / => / 138/// 139/// @param path A path that is modified to not have a file component. 140/// @returns errc::success if \a path's file name has been removed (or there was 141/// not one to begin with), otherwise a platform specific error_code. 142error_code remove_filename(SmallVectorImpl<char> &path); 143 144/// @brief Replace the file extension of \a path with \a extension. 145/// 146/// ./filename.cpp => ./filename.extension 147/// ./filename => ./filename.extension 148/// ./ => ./.extension 149/// 150/// @param path A path that has its extension replaced with \a extension. 151/// @param extension The extension to be added. It may be empty. It may also 152/// optionally start with a '.', if it does not, one will be 153/// prepended. 154/// @returns errc::success if \a path's extension has been replaced, otherwise a 155/// platform specific error_code. 156error_code replace_extension(SmallVectorImpl<char> &path, 157 const Twine &extension); 158 159/// @brief Append to path. 160/// 161/// /foo + bar/f => /foo/bar/f 162/// /foo/ + bar/f => /foo/bar/f 163/// foo + bar/f => foo/bar/f 164/// 165/// @param path Set to \a path + \a component. 166/// @param component The component to be appended to \a path. 167/// @returns errc::success if \a component has been appended to \a path, 168/// otherwise a platform specific error_code. 169error_code append(SmallVectorImpl<char> &path, const Twine &a, 170 const Twine &b = "", 171 const Twine &c = "", 172 const Twine &d = ""); 173 174/// @brief Append to path. 175/// 176/// /foo + [bar,f] => /foo/bar/f 177/// /foo/ + [bar,f] => /foo/bar/f 178/// foo + [bar,f] => foo/bar/f 179/// 180/// @param path Set to \a path + [\a begin, \a end). 181/// @param begin Start of components to append. 182/// @param end One past the end of components to append. 183/// @returns errc::success if [\a begin, \a end) has been appended to \a path, 184/// otherwise a platform specific error_code. 185error_code append(SmallVectorImpl<char> &path, 186 const_iterator begin, const_iterator end); 187 188/// @} 189/// @name Transforms (or some other better name) 190/// @{ 191 192/// Convert path to the native form. This is used to give paths to users and 193/// operating system calls in the platform's normal way. For example, on Windows 194/// all '/' are converted to '\'. 195/// 196/// @param path A path that is transformed to native format. 197/// @param result Holds the result of the transformation. 198/// @returns errc::success if \a path has been transformed and stored in result, 199/// otherwise a platform specific error_code. 200error_code native(const Twine &path, SmallVectorImpl<char> &result); 201 202/// @} 203/// @name Lexical Observers 204/// @{ 205 206/// @brief Get root name. 207/// 208/// //net/hello => //net 209/// c:/hello => c: (on Windows, on other platforms nothing) 210/// /hello => <empty> 211/// 212/// @param path Input path. 213/// @param result Set to the root name of \a path if it has one, otherwise "". 214/// @results errc::success if result has been successfully set, otherwise a 215/// platform specific error_code. 216error_code root_name(const StringRef &path, StringRef &result); 217 218/// @brief Get root directory. 219/// 220/// /goo/hello => / 221/// c:/hello => / 222/// d/file.txt => <empty> 223/// 224/// @param path Input path. 225/// @param result Set to the root directory of \a path if it has one, otherwise 226/// "". 227/// @results errc::success if result has been successfully set, otherwise a 228/// platform specific error_code. 229error_code root_directory(const StringRef &path, StringRef &result); 230 231/// @brief Get root path. 232/// 233/// Equivalent to root_name + root_directory. 234/// 235/// @param path Input path. 236/// @param result Set to the root path of \a path if it has one, otherwise "". 237/// @results errc::success if result has been successfully set, otherwise a 238/// platform specific error_code. 239error_code root_path(const StringRef &path, StringRef &result); 240 241/// @brief Get relative path. 242/// 243/// C:\hello\world => hello\world 244/// foo/bar => foo/bar 245/// /foo/bar => foo/bar 246/// 247/// @param path Input path. 248/// @param result Set to the path starting after root_path if one exists, 249/// otherwise "". 250/// @results errc::success if result has been successfully set, otherwise a 251/// platform specific error_code. 252error_code relative_path(const StringRef &path, StringRef &result); 253 254/// @brief Get parent path. 255/// 256/// / => <empty> 257/// /foo => / 258/// foo/../bar => foo/.. 259/// 260/// @param path Input path. 261/// @param result Set to the parent path of \a path if one exists, otherwise "". 262/// @results errc::success if result has been successfully set, otherwise a 263/// platform specific error_code. 264error_code parent_path(const StringRef &path, StringRef &result); 265 266/// @brief Get filename. 267/// 268/// /foo.txt => foo.txt 269/// . => . 270/// .. => .. 271/// / => / 272/// 273/// @param path Input path. 274/// @param result Set to the filename part of \a path. This is defined as the 275/// last component of \a path. 276/// @results errc::success if result has been successfully set, otherwise a 277/// platform specific error_code. 278error_code filename(const StringRef &path, StringRef &result); 279 280/// @brief Get stem. 281/// 282/// If filename contains a dot but not solely one or two dots, result is the 283/// substring of filename ending at (but not including) the last dot. Otherwise 284/// it is filename. 285/// 286/// /foo/bar.txt => bar 287/// /foo/bar => bar 288/// /foo/.txt => <empty> 289/// /foo/. => . 290/// /foo/.. => .. 291/// 292/// @param path Input path. 293/// @param result Set to the stem of \a path. 294/// @results errc::success if result has been successfully set, otherwise a 295/// platform specific error_code. 296error_code stem(const StringRef &path, StringRef &result); 297 298/// @brief Get extension. 299/// 300/// If filename contains a dot but not solely one or two dots, result is the 301/// substring of filename starting at (and including) the last dot, and ending 302/// at the end of \a path. Otherwise "". 303/// 304/// /foo/bar.txt => .txt 305/// /foo/bar => <empty> 306/// /foo/.txt => .txt 307/// 308/// @param path Input path. 309/// @param result Set to the extension of \a path. 310/// @results errc::success if result has been successfully set, otherwise a 311/// platform specific error_code. 312error_code extension(const StringRef &path, StringRef &result); 313 314/// @brief Has root name? 315/// 316/// root_name != "" 317/// 318/// @param path Input path. 319/// @param result Set to true if the path has a root name, false otherwise. 320/// @results errc::success if result has been successfully set, otherwise a 321/// platform specific error_code. 322error_code has_root_name(const Twine &path, bool &result); 323 324/// @brief Has root directory? 325/// 326/// root_directory != "" 327/// 328/// @param path Input path. 329/// @param result Set to true if the path has a root directory, false otherwise. 330/// @results errc::success if result has been successfully set, otherwise a 331/// platform specific error_code. 332error_code has_root_directory(const Twine &path, bool &result); 333 334/// @brief Has root path? 335/// 336/// root_path != "" 337/// 338/// @param path Input path. 339/// @param result Set to true if the path has a root path, false otherwise. 340/// @results errc::success if result has been successfully set, otherwise a 341/// platform specific error_code. 342error_code has_root_path(const Twine &path, bool &result); 343 344/// @brief Has relative path? 345/// 346/// relative_path != "" 347/// 348/// @param path Input path. 349/// @param result Set to true if the path has a relative path, false otherwise. 350/// @results errc::success if result has been successfully set, otherwise a 351/// platform specific error_code. 352error_code has_relative_path(const Twine &path, bool &result); 353 354/// @brief Has parent path? 355/// 356/// parent_path != "" 357/// 358/// @param path Input path. 359/// @param result Set to true if the path has a parent path, false otherwise. 360/// @results errc::success if result has been successfully set, otherwise a 361/// platform specific error_code. 362error_code has_parent_path(const Twine &path, bool &result); 363 364/// @brief Has filename? 365/// 366/// filename != "" 367/// 368/// @param path Input path. 369/// @param result Set to true if the path has a filename, false otherwise. 370/// @results errc::success if result has been successfully set, otherwise a 371/// platform specific error_code. 372error_code has_filename(const Twine &path, bool &result); 373 374/// @brief Has stem? 375/// 376/// stem != "" 377/// 378/// @param path Input path. 379/// @param result Set to true if the path has a stem, false otherwise. 380/// @results errc::success if result has been successfully set, otherwise a 381/// platform specific error_code. 382error_code has_stem(const Twine &path, bool &result); 383 384/// @brief Has extension? 385/// 386/// extension != "" 387/// 388/// @param path Input path. 389/// @param result Set to true if the path has a extension, false otherwise. 390/// @results errc::success if result has been successfully set, otherwise a 391/// platform specific error_code. 392error_code has_extension(const Twine &path, bool &result); 393 394/// @brief Is path absolute? 395/// 396/// @param path Input path. 397/// @param result Set to true if the path is absolute, false if it is not. 398/// @results errc::success if result has been successfully set, otherwise a 399/// platform specific error_code. 400error_code is_absolute(const Twine &path, bool &result); 401 402/// @brief Is path relative? 403/// 404/// @param path Input path. 405/// @param result Set to true if the path is relative, false if it is not. 406/// @results errc::success if result has been successfully set, otherwise a 407/// platform specific error_code. 408error_code is_relative(const Twine &path, bool &result); 409// end purely lexical. 410 411} // end namespace path 412} // end namespace sys 413} // end namespace llvm 414 415#endif 416