1 //===-- FileSpec.h ----------------------------------------------*- 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 #ifndef liblldb_FileSpec_h_ 11 #define liblldb_FileSpec_h_ 12 13 #include <functional> 14 #include <string> 15 16 #include "lldb/Utility/ConstString.h" 17 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Support/FileSystem.h" 20 #include "llvm/Support/FormatVariadic.h" 21 #include "llvm/Support/Path.h" 22 23 #include <stddef.h> 24 #include <stdint.h> 25 26 namespace lldb_private { 27 class Stream; 28 } 29 namespace llvm { 30 class Triple; 31 } 32 namespace llvm { 33 class raw_ostream; 34 } 35 namespace llvm { 36 template <typename T> class SmallVectorImpl; 37 } 38 39 namespace lldb_private { 40 41 //---------------------------------------------------------------------- 42 /// @class FileSpec FileSpec.h "lldb/Host/FileSpec.h" 43 /// A file utility class. 44 /// 45 /// A file specification class that divides paths up into a directory 46 /// and basename. These string values of the paths are put into uniqued string 47 /// pools for fast comparisons and efficient memory usage. 48 /// 49 /// Another reason the paths are split into the directory and basename is to 50 /// allow efficient debugger searching. Often in a debugger the user types in 51 /// the basename of the file, for example setting a breakpoint by file and 52 /// line, or specifying a module (shared library) to limit the scope in which 53 /// to execute a command. The user rarely types in a full path. When the paths 54 /// are already split up, it makes it easy for us to compare only the 55 /// basenames of a lot of file specifications without having to split up the 56 /// file path each time to get to the basename. 57 //---------------------------------------------------------------------- 58 class FileSpec { 59 public: 60 using Style = llvm::sys::path::Style; 61 62 FileSpec(); 63 64 //------------------------------------------------------------------ 65 /// Constructor with path. 66 /// 67 /// Takes a path to a file which can be just a filename, or a full path. If 68 /// \a path is not nullptr or empty, this function will call 69 /// FileSpec::SetFile (const char *path). 70 /// 71 /// @param[in] path 72 /// The full or partial path to a file. 73 /// 74 /// @param[in] style 75 /// The style of the path 76 /// 77 /// @see FileSpec::SetFile (const char *path) 78 //------------------------------------------------------------------ 79 explicit FileSpec(llvm::StringRef path, Style style = Style::native); 80 81 explicit FileSpec(llvm::StringRef path, const llvm::Triple &Triple); 82 83 //------------------------------------------------------------------ 84 /// Copy constructor 85 /// 86 /// Makes a copy of the uniqued directory and filename strings from \a rhs. 87 /// 88 /// @param[in] rhs 89 /// A const FileSpec object reference to copy. 90 //------------------------------------------------------------------ 91 FileSpec(const FileSpec &rhs); 92 93 //------------------------------------------------------------------ 94 /// Copy constructor 95 /// 96 /// Makes a copy of the uniqued directory and filename strings from \a rhs 97 /// if it is not nullptr. 98 /// 99 /// @param[in] rhs 100 /// A const FileSpec object pointer to copy if non-nullptr. 101 //------------------------------------------------------------------ 102 FileSpec(const FileSpec *rhs); 103 104 //------------------------------------------------------------------ 105 /// Destructor. 106 //------------------------------------------------------------------ 107 ~FileSpec(); 108 109 bool DirectoryEquals(const FileSpec &other) const; 110 111 bool FileEquals(const FileSpec &other) const; 112 113 //------------------------------------------------------------------ 114 /// Assignment operator. 115 /// 116 /// Makes a copy of the uniqued directory and filename strings from \a rhs. 117 /// 118 /// @param[in] rhs 119 /// A const FileSpec object reference to assign to this object. 120 /// 121 /// @return 122 /// A const reference to this object. 123 //------------------------------------------------------------------ 124 const FileSpec &operator=(const FileSpec &rhs); 125 126 //------------------------------------------------------------------ 127 /// Equal to operator 128 /// 129 /// Tests if this object is equal to \a rhs. 130 /// 131 /// @param[in] rhs 132 /// A const FileSpec object reference to compare this object 133 /// to. 134 /// 135 /// @return 136 /// \b true if this object is equal to \a rhs, \b false 137 /// otherwise. 138 //------------------------------------------------------------------ 139 bool operator==(const FileSpec &rhs) const; 140 141 //------------------------------------------------------------------ 142 /// Not equal to operator 143 /// 144 /// Tests if this object is not equal to \a rhs. 145 /// 146 /// @param[in] rhs 147 /// A const FileSpec object reference to compare this object 148 /// to. 149 /// 150 /// @return 151 /// \b true if this object is equal to \a rhs, \b false 152 /// otherwise. 153 //------------------------------------------------------------------ 154 bool operator!=(const FileSpec &rhs) const; 155 156 //------------------------------------------------------------------ 157 /// Less than to operator 158 /// 159 /// Tests if this object is less than \a rhs. 160 /// 161 /// @param[in] rhs 162 /// A const FileSpec object reference to compare this object 163 /// to. 164 /// 165 /// @return 166 /// \b true if this object is less than \a rhs, \b false 167 /// otherwise. 168 //------------------------------------------------------------------ 169 bool operator<(const FileSpec &rhs) const; 170 171 //------------------------------------------------------------------ 172 /// Convert to pointer operator. 173 /// 174 /// This allows code to check a FileSpec object to see if it contains 175 /// anything valid using code such as: 176 /// 177 /// @code 178 /// FileSpec file_spec(...); 179 /// if (file_spec) 180 /// { ... 181 /// @endcode 182 /// 183 /// @return 184 /// A pointer to this object if either the directory or filename 185 /// is valid, nullptr otherwise. 186 //------------------------------------------------------------------ 187 explicit operator bool() const; 188 189 //------------------------------------------------------------------ 190 /// Logical NOT operator. 191 /// 192 /// This allows code to check a FileSpec object to see if it is invalid 193 /// using code such as: 194 /// 195 /// @code 196 /// FileSpec file_spec(...); 197 /// if (!file_spec) 198 /// { ... 199 /// @endcode 200 /// 201 /// @return 202 /// Returns \b true if the object has an empty directory and 203 /// filename, \b false otherwise. 204 //------------------------------------------------------------------ 205 bool operator!() const; 206 207 //------------------------------------------------------------------ 208 /// Clears the object state. 209 /// 210 /// Clear this object by releasing both the directory and filename string 211 /// values and reverting them to empty strings. 212 //------------------------------------------------------------------ 213 void Clear(); 214 215 //------------------------------------------------------------------ 216 /// Compare two FileSpec objects. 217 /// 218 /// If \a full is true, then both the directory and the filename must match. 219 /// If \a full is false, then the directory names for \a lhs and \a rhs are 220 /// only compared if they are both not empty. This allows a FileSpec object 221 /// to only contain a filename and it can match FileSpec objects that have 222 /// matching filenames with different paths. 223 /// 224 /// @param[in] lhs 225 /// A const reference to the Left Hand Side object to compare. 226 /// 227 /// @param[in] rhs 228 /// A const reference to the Right Hand Side object to compare. 229 /// 230 /// @param[in] full 231 /// If true, then both the directory and filenames will have to 232 /// match for a compare to return zero (equal to). If false 233 /// and either directory from \a lhs or \a rhs is empty, then 234 /// only the filename will be compared, else a full comparison 235 /// is done. 236 /// 237 /// @return 238 /// @li -1 if \a lhs is less than \a rhs 239 /// @li 0 if \a lhs is equal to \a rhs 240 /// @li 1 if \a lhs is greater than \a rhs 241 //------------------------------------------------------------------ 242 static int Compare(const FileSpec &lhs, const FileSpec &rhs, bool full); 243 244 static bool Equal(const FileSpec &a, const FileSpec &b, bool full); 245 246 //------------------------------------------------------------------ 247 /// Case sensitivity of path. 248 /// 249 /// @return 250 /// \b true if the file path is case sensitive (POSIX), false 251 /// if case insensitive (Windows). 252 //------------------------------------------------------------------ IsCaseSensitive()253 bool IsCaseSensitive() const { return m_style != Style::windows; } 254 255 //------------------------------------------------------------------ 256 /// Dump this object to a Stream. 257 /// 258 /// Dump the object to the supplied stream \a s. If the object contains a 259 /// valid directory name, it will be displayed followed by a directory 260 /// delimiter, and the filename. 261 /// 262 /// @param[in] s 263 /// The stream to which to dump the object description. 264 //------------------------------------------------------------------ 265 void Dump(Stream *s) const; 266 267 Style GetPathStyle() const; 268 269 //------------------------------------------------------------------ 270 /// Directory string get accessor. 271 /// 272 /// @return 273 /// A reference to the directory string object. 274 //------------------------------------------------------------------ 275 ConstString &GetDirectory(); 276 277 //------------------------------------------------------------------ 278 /// Directory string const get accessor. 279 /// 280 /// @return 281 /// A const reference to the directory string object. 282 //------------------------------------------------------------------ 283 const ConstString &GetDirectory() const; 284 285 //------------------------------------------------------------------ 286 /// Filename string get accessor. 287 /// 288 /// @return 289 /// A reference to the filename string object. 290 //------------------------------------------------------------------ 291 ConstString &GetFilename(); 292 293 //------------------------------------------------------------------ 294 /// Filename string const get accessor. 295 /// 296 /// @return 297 /// A const reference to the filename string object. 298 //------------------------------------------------------------------ 299 const ConstString &GetFilename() const; 300 301 //------------------------------------------------------------------ 302 /// Returns true if the filespec represents an implementation source file 303 /// (files with a ".c", ".cpp", ".m", ".mm" (many more) extension). 304 /// 305 /// @return 306 /// \b true if the filespec represents an implementation source 307 /// file, \b false otherwise. 308 //------------------------------------------------------------------ 309 bool IsSourceImplementationFile() const; 310 311 //------------------------------------------------------------------ 312 /// Returns true if the filespec represents a relative path. 313 /// 314 /// @return 315 /// \b true if the filespec represents a relative path, 316 /// \b false otherwise. 317 //------------------------------------------------------------------ 318 bool IsRelative() const; 319 320 //------------------------------------------------------------------ 321 /// Returns true if the filespec represents an absolute path. 322 /// 323 /// @return 324 /// \b true if the filespec represents an absolute path, 325 /// \b false otherwise. 326 //------------------------------------------------------------------ 327 bool IsAbsolute() const; 328 329 /// Temporary helper for FileSystem change. SetPath(llvm::StringRef p)330 void SetPath(llvm::StringRef p) { SetFile(p); } 331 332 //------------------------------------------------------------------ 333 /// Extract the full path to the file. 334 /// 335 /// Extract the directory and path into a fixed buffer. This is needed as 336 /// the directory and path are stored in separate string values. 337 /// 338 /// @param[out] path 339 /// The buffer in which to place the extracted full path. 340 /// 341 /// @param[in] max_path_length 342 /// The maximum length of \a path. 343 /// 344 /// @return 345 /// Returns the number of characters that would be needed to 346 /// properly copy the full path into \a path. If the returned 347 /// number is less than \a max_path_length, then the path is 348 /// properly copied and terminated. If the return value is 349 /// >= \a max_path_length, then the path was truncated (but is 350 /// still NULL terminated). 351 //------------------------------------------------------------------ 352 size_t GetPath(char *path, size_t max_path_length, 353 bool denormalize = true) const; 354 355 //------------------------------------------------------------------ 356 /// Extract the full path to the file. 357 /// 358 /// Extract the directory and path into a std::string, which is returned. 359 /// 360 /// @return 361 /// Returns a std::string with the directory and filename 362 /// concatenated. 363 //------------------------------------------------------------------ 364 std::string GetPath(bool denormalize = true) const; 365 366 const char *GetCString(bool denormalize = true) const; 367 368 //------------------------------------------------------------------ 369 /// Extract the full path to the file. 370 /// 371 /// Extract the directory and path into an llvm::SmallVectorImpl<> 372 /// 373 /// @return 374 /// Returns a std::string with the directory and filename 375 /// concatenated. 376 //------------------------------------------------------------------ 377 void GetPath(llvm::SmallVectorImpl<char> &path, 378 bool denormalize = true) const; 379 380 //------------------------------------------------------------------ 381 /// Extract the extension of the file. 382 /// 383 /// Returns a ConstString that represents the extension of the filename for 384 /// this FileSpec object. If this object does not represent a file, or the 385 /// filename has no extension, ConstString(nullptr) is returned. The dot 386 /// ('.') character is not returned as part of the extension 387 /// 388 /// @return 389 /// Returns the extension of the file as a ConstString object. 390 //------------------------------------------------------------------ 391 ConstString GetFileNameExtension() const; 392 393 //------------------------------------------------------------------ 394 /// Return the filename without the extension part 395 /// 396 /// Returns a ConstString that represents the filename of this object 397 /// without the extension part (e.g. for a file named "foo.bar", "foo" is 398 /// returned) 399 /// 400 /// @return 401 /// Returns the filename without extension 402 /// as a ConstString object. 403 //------------------------------------------------------------------ 404 ConstString GetFileNameStrippingExtension() const; 405 406 //------------------------------------------------------------------ 407 /// Get the memory cost of this object. 408 /// 409 /// Return the size in bytes that this object takes in memory. This returns 410 /// the size in bytes of this object, not any shared string values it may 411 /// refer to. 412 /// 413 /// @return 414 /// The number of bytes that this object occupies in memory. 415 /// 416 /// @see ConstString::StaticMemorySize () 417 //------------------------------------------------------------------ 418 size_t MemorySize() const; 419 420 //------------------------------------------------------------------ 421 /// Change the file specified with a new path. 422 /// 423 /// Update the contents of this object with a new path. The path will be 424 /// split up into a directory and filename and stored as uniqued string 425 /// values for quick comparison and efficient memory usage. 426 /// 427 /// @param[in] path 428 /// A full, partial, or relative path to a file. 429 /// 430 /// @param[in] resolve_path 431 /// If \b true, then we will try to resolve links the path using 432 /// the static FileSpec::Resolve. 433 //------------------------------------------------------------------ 434 void SetFile(llvm::StringRef path, Style style); 435 436 void SetFile(llvm::StringRef path, const llvm::Triple &Triple); 437 IsResolved()438 bool IsResolved() const { return m_is_resolved; } 439 440 //------------------------------------------------------------------ 441 /// Set if the file path has been resolved or not. 442 /// 443 /// If you know a file path is already resolved and avoided passing a \b 444 /// true parameter for any functions that take a "bool resolve_path" 445 /// parameter, you can set the value manually using this call to make sure 446 /// we don't try and resolve it later, or try and resolve a path that has 447 /// already been resolved. 448 /// 449 /// @param[in] is_resolved 450 /// A boolean value that will replace the current value that 451 /// indicates if the paths in this object have been resolved. 452 //------------------------------------------------------------------ SetIsResolved(bool is_resolved)453 void SetIsResolved(bool is_resolved) { m_is_resolved = is_resolved; } 454 455 FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const; 456 FileSpec CopyByRemovingLastPathComponent() const; 457 458 void PrependPathComponent(llvm::StringRef component); 459 void PrependPathComponent(const FileSpec &new_path); 460 461 void AppendPathComponent(llvm::StringRef component); 462 void AppendPathComponent(const FileSpec &new_path); 463 464 //------------------------------------------------------------------ 465 /// Removes the last path component by replacing the current path with its 466 /// parent. When the current path has no parent, this is a no-op. 467 /// 468 /// @return 469 /// A boolean value indicating whether the path was updated. 470 //------------------------------------------------------------------ 471 bool RemoveLastPathComponent(); 472 473 ConstString GetLastPathComponent() const; 474 475 protected: 476 //------------------------------------------------------------------ 477 // Convenience method for setting the file without changing the style. 478 //------------------------------------------------------------------ 479 void SetFile(llvm::StringRef path); 480 481 //------------------------------------------------------------------ 482 // Member variables 483 //------------------------------------------------------------------ 484 ConstString m_directory; ///< The uniqued directory path 485 ConstString m_filename; ///< The uniqued filename path 486 mutable bool m_is_resolved = false; ///< True if this path has been resolved. 487 Style m_style; ///< The syntax that this path uses (e.g. Windows / Posix) 488 }; 489 490 //---------------------------------------------------------------------- 491 /// Dump a FileSpec object to a stream 492 //---------------------------------------------------------------------- 493 Stream &operator<<(Stream &s, const FileSpec &f); 494 495 } // namespace lldb_private 496 497 namespace llvm { 498 499 /// Implementation of format_provider<T> for FileSpec. 500 /// 501 /// The options string of a FileSpec has the grammar: 502 /// 503 /// file_spec_options :: (empty) | F | D 504 /// 505 /// ======================================================= 506 /// | style | Meaning | Example | 507 /// ------------------------------------------------------- 508 /// | | | Input | Output | 509 /// ======================================================= 510 /// | F | Only print filename | /foo/bar | bar | 511 /// | D | Only print directory | /foo/bar | /foo/ | 512 /// | (empty) | Print file and dir | | | 513 /// ======================================================= 514 /// 515 /// Any other value is considered an invalid format string. 516 /// 517 template <> struct format_provider<lldb_private::FileSpec> { 518 static void format(const lldb_private::FileSpec &F, llvm::raw_ostream &Stream, 519 StringRef Style); 520 }; 521 } // namespace llvm 522 523 #endif // liblldb_FileSpec_h_ 524