13#include "llvm/ADT/SmallString.h"
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/ADT/StringExtras.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/ADT/Twine.h"
18#include "llvm/Support/ErrorOr.h"
19#include "llvm/Support/FileSystem.h"
20#include "llvm/Support/Program.h"
21#include "llvm/Support/raw_ostream.h"
22#include "llvm/TargetParser/Triple.h"
26#include <system_error>
41 return FileSpec::Style::windows;
43 return FileSpec::Style::posix;
48 return llvm::sys::path::is_style_posix(style);
52 return llvm::sys::path::get_separator(style).data();
56 return GetPathSeparators(style)[0];
60 if (PathStyleIsPosix(style))
63 std::replace(path.begin(), path.end(),
'/',
'\\');
90inline char safeCharAtIndex(
const llvm::StringRef &path,
size_t i) {
113bool needsNormalization(
const llvm::StringRef &path) {
119 for (
auto i = path.find_first_of(
"\\/"); i != llvm::StringRef::npos;
120 i = path.find_first_of(
"\\/", i + 1)) {
121 const auto next = safeCharAtIndex(path, i+1);
137 const auto next_next = safeCharAtIndex(path, i+2);
145 const auto next_next_next = safeCharAtIndex(path, i+3);
146 switch (next_next_next) {
176 m_style = (style == Style::native) ? GetNativeStyle() : style;
178 if (pathname.empty())
181 llvm::SmallString<128> resolved(pathname);
184 if (needsNormalization(resolved))
185 llvm::sys::path::remove_dots(resolved,
true,
m_style);
189 std::replace(resolved.begin(), resolved.end(),
'\\',
'/');
191 if (resolved.empty()) {
201 llvm::StringRef filename = llvm::sys::path::filename(resolved,
m_style);
202 if(!filename.empty())
205 llvm::StringRef directory = llvm::sys::path::parent_path(resolved,
m_style);
206 if(!directory.empty())
211 return SetFile(path, triple.isOSWindows() ? Style::windows : Style::posix);
219FileSpec::operator bool()
const {
return m_filename || m_directory; }
303 return pattern == file;
309std::optional<FileSpec::Style>
311 if (absolute_path.starts_with(
"/"))
313 if (absolute_path.starts_with(R
"(\\)"))
314 return Style::windows;
315 if (absolute_path.size() >= 3 && llvm::isAlpha(absolute_path[0]) &&
316 (absolute_path.substr(1, 2) == R
"(:\)" ||
317 absolute_path.substr(1, 2) == R"(:/)"))
318 return Style::windows;
326 std::string path{
GetPath(
true)};
328 char path_separator = GetPreferredPathSeparator(
m_style);
329 if (!
m_filename && !path.empty() && path.back() != path_separator)
368 bool denormalize)
const {
372 std::string result =
GetPath(denormalize);
373 ::snprintf(path, path_max_len,
"%s", result.c_str());
374 return std::min(path_max_len - 1, result.length());
378 llvm::SmallString<64> result;
380 return static_cast<std::string
>(result);
388 bool denormalize)
const {
396 path.insert(path.end(),
'/');
399 if (denormalize && !path.empty())
425 llvm::SmallString<64> current_path;
427 if (llvm::sys::path::has_parent_path(current_path,
m_style))
434 llvm::SmallString<64> new_path(component);
435 llvm::SmallString<64> current_path;
437 llvm::sys::path::append(new_path,
438 llvm::sys::path::begin(current_path,
m_style),
439 llvm::sys::path::end(current_path),
m_style);
448 llvm::SmallString<64> current_path;
450 llvm::sys::path::append(current_path,
m_style, component);
459 llvm::SmallString<64> current_path;
461 if (llvm::sys::path::has_parent_path(current_path,
m_style)) {
469 std::vector<llvm::StringRef> components;
474 for (
auto iter = dir_begin; iter != dir_end; ++iter) {
475 if (*iter ==
"/" || *iter ==
".")
478 components.push_back(*iter);
496 if (extension.empty())
500 "^.([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|["
501 "cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO]["
502 "rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])"
504 return g_source_file_regex.
Execute(extension);
518 llvm::SmallString<64> path;
523 if (path[0] ==
'~' || llvm::sys::path::is_absolute(path,
m_style))
535void llvm::format_provider<FileSpec>::format(
const FileSpec &F,
538 assert((Style.empty() || Style.equals_insensitive(
"F") ||
539 Style.equals_insensitive(
"D")) &&
540 "Invalid FileSpec style!");
545 if (dir.empty() && file.empty()) {
550 if (Style.equals_insensitive(
"F")) {
551 Stream << (file.empty() ?
"(empty)" : file);
560 llvm::SmallString<64> denormalized_dir = dir;
562 Stream << denormalized_dir;
566 if (Style.equals_insensitive(
"D")) {
A uniqued constant string class.
size_t MemorySize() const
Get the memory cost of this object.
static int Compare(ConstString lhs, ConstString rhs, const bool case_sensitive=true)
Compare two string objects.
static bool Equals(ConstString lhs, ConstString rhs, const bool case_sensitive=true)
Equal to operator.
bool IsEmpty() const
Test for empty string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
void SetString(llvm::StringRef s)
void Clear()
Clear this object's state.
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
void AppendPathComponent(llvm::StringRef component)
void SetDirectory(ConstString directory)
Directory string set accessor.
static bool Equal(const FileSpec &a, const FileSpec &b, bool full)
static std::optional< Style > GuessPathStyle(llvm::StringRef absolute_path)
Attempt to guess path style for a given path string.
static bool Match(const FileSpec &pattern, const FileSpec &file)
Match FileSpec pattern against FileSpec file.
bool IsRelative() const
Returns true if the filespec represents a relative path.
bool FileEquals(const FileSpec &other) const
bool operator<(const FileSpec &rhs) const
Less than to operator.
const ConstString & GetFilename() const
Filename string const get accessor.
bool RemoveLastPathComponent()
Removes the last path component by replacing the current path with its parent.
void MakeAbsolute(const FileSpec &dir)
Make the FileSpec absolute by treating it relative to dir.
bool operator!() const
Logical NOT operator.
ConstString m_filename
The unique'd filename path.
std::vector< llvm::StringRef > GetComponents() const
Gets the components of the FileSpec's path.
void ClearDirectory()
Clear the directory in this object.
const ConstString & GetDirectory() const
Directory string const get accessor.
bool IsCaseSensitive() const
Case sensitivity of path.
bool DirectoryEquals(const FileSpec &other) const
bool IsAbsolute() const
Returns true if the filespec represents an absolute path.
Style GetPathStyle() const
void PathWasModified()
Called anytime m_directory or m_filename is changed to clear any cached state in this object.
size_t MemorySize() const
Get the memory cost of this object.
static int Compare(const FileSpec &lhs, const FileSpec &rhs, bool full)
Compare two FileSpec objects.
Style m_style
The syntax that this path uses. (e.g. Windows / Posix)
ConstString GetFileNameStrippingExtension() const
Return the filename without the extension part.
void PrependPathComponent(llvm::StringRef component)
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
void Clear()
Clears the object state.
Absolute m_absolute
Cache whether this path is absolute.
bool operator!=(const FileSpec &rhs) const
Not equal to operator.
void Dump(llvm::raw_ostream &s) const
Dump this object to a Stream.
ConstString GetPathAsConstString(bool denormalize=true) const
Get the full path as a ConstString.
bool IsSourceImplementationFile() const
Returns true if the filespec represents an implementation source file (files with a "....
ConstString m_directory
The unique'd directory path.
bool operator==(const FileSpec &rhs) const
Equal to operator.
FileSpec CopyByRemovingLastPathComponent() const
llvm::StringRef GetFileNameExtension() const
Extract the extension of the file.
llvm::sys::path::Style Style
void SetFilename(ConstString filename)
Filename string set accessor.
void ClearFilename()
Clear the filename in this object.
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
A stream class that can stream formatted output to a file.
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
A class that represents a running process on the host machine.
Stream & operator<<(Stream &s, const Mangled &obj)