13#include "llvm/ADT/SmallString.h"
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/ADT/StringRef.h"
16#include "llvm/ADT/Twine.h"
17#include "llvm/Support/ErrorOr.h"
18#include "llvm/Support/FileSystem.h"
19#include "llvm/Support/Program.h"
20#include "llvm/Support/raw_ostream.h"
21#include "llvm/TargetParser/Triple.h"
25#include <system_error>
40 return FileSpec::Style::windows;
42 return FileSpec::Style::posix;
47 return llvm::sys::path::is_style_posix(style);
51 return llvm::sys::path::get_separator(style).data();
55 return GetPathSeparators(style)[0];
59 if (PathStyleIsPosix(style))
62 std::replace(path.begin(), path.end(),
'/',
'\\');
89inline char safeCharAtIndex(
const llvm::StringRef &path,
size_t i) {
112bool needsNormalization(
const llvm::StringRef &path) {
118 for (
auto i = path.find_first_of(
"\\/"); i != llvm::StringRef::npos;
119 i = path.find_first_of(
"\\/", i + 1)) {
120 const auto next = safeCharAtIndex(path, i+1);
136 const auto next_next = safeCharAtIndex(path, i+2);
144 const auto next_next_next = safeCharAtIndex(path, i+3);
145 switch (next_next_next) {
175 m_style = (style == Style::native) ? GetNativeStyle() : style;
177 if (pathname.empty())
180 llvm::SmallString<128> resolved(pathname);
183 if (needsNormalization(resolved))
184 llvm::sys::path::remove_dots(resolved,
true,
m_style);
188 std::replace(resolved.begin(), resolved.end(),
'\\',
'/');
190 if (resolved.empty()) {
200 llvm::StringRef filename = llvm::sys::path::filename(resolved,
m_style);
201 if(!filename.empty())
204 llvm::StringRef directory = llvm::sys::path::parent_path(resolved,
m_style);
205 if(!directory.empty())
210 return SetFile(path, triple.isOSWindows() ? Style::windows : Style::posix);
218FileSpec::operator bool()
const {
return m_filename || m_directory; }
302 return pattern == file;
308std::optional<FileSpec::Style>
310 if (absolute_path.startswith(
"/"))
312 if (absolute_path.startswith(R
"(\\)"))
313 return Style::windows;
314 if (absolute_path.size() >= 3 && llvm::isAlpha(absolute_path[0]) &&
315 (absolute_path.substr(1, 2) == R
"(:\)" ||
316 absolute_path.substr(1, 2) == R"(:/)"))
317 return Style::windows;
325 std::string path{
GetPath(
true)};
327 char path_separator = GetPreferredPathSeparator(
m_style);
328 if (!
m_filename && !path.empty() && path.back() != path_separator)
367 bool denormalize)
const {
371 std::string result =
GetPath(denormalize);
372 ::snprintf(path, path_max_len,
"%s", result.c_str());
373 return std::min(path_max_len - 1, result.length());
377 llvm::SmallString<64> result;
379 return static_cast<std::string
>(result);
387 bool denormalize)
const {
395 path.insert(path.end(),
'/');
398 if (denormalize && !path.empty())
424 llvm::SmallString<64> current_path;
426 if (llvm::sys::path::has_parent_path(current_path,
m_style))
433 llvm::SmallString<64> new_path(component);
434 llvm::SmallString<64> current_path;
436 llvm::sys::path::append(new_path,
437 llvm::sys::path::begin(current_path,
m_style),
438 llvm::sys::path::end(current_path),
m_style);
447 llvm::SmallString<64> current_path;
449 llvm::sys::path::append(current_path,
m_style, component);
458 llvm::SmallString<64> current_path;
460 if (llvm::sys::path::has_parent_path(current_path,
m_style)) {
468 std::vector<llvm::StringRef> components;
473 for (
auto iter = dir_begin; iter != dir_end; ++iter) {
474 if (*iter ==
"/" || *iter ==
".")
477 components.push_back(*iter);
495 if (extension.empty())
499 "^.([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|["
500 "cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO]["
501 "rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])"
503 return g_source_file_regex.
Execute(extension);
517 llvm::SmallString<64> path;
522 if (path[0] ==
'~' || llvm::sys::path::is_absolute(path,
m_style))
534void llvm::format_provider<FileSpec>::format(
const FileSpec &F,
537 assert((Style.empty() || Style.equals_insensitive(
"F") ||
538 Style.equals_insensitive(
"D")) &&
539 "Invalid FileSpec style!");
544 if (dir.empty() && file.empty()) {
549 if (Style.equals_insensitive(
"F")) {
550 Stream << (file.empty() ?
"(empty)" : file);
559 llvm::SmallString<64> denormalized_dir = dir;
561 Stream << denormalized_dir;
565 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.
void SetString(const llvm::StringRef &s)
bool IsEmpty() const
Test for empty string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
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 uniqued 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 absoluteness.
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 uniqued 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 SourceLocationSpec &loc)
Dump a SourceLocationSpec object to a stream.