summaryrefslogtreecommitdiffstats
path: root/lldb/source/Host/common/FileSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Host/common/FileSpec.cpp')
-rw-r--r--lldb/source/Host/common/FileSpec.cpp151
1 files changed, 52 insertions, 99 deletions
diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp
index b966380c133..f1bd204d02f 100644
--- a/lldb/source/Host/common/FileSpec.cpp
+++ b/lldb/source/Host/common/FileSpec.cpp
@@ -533,120 +533,73 @@ bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full,
if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
return ConstString::Equals(a.m_filename, b.m_filename, case_sensitive);
- else if (remove_backups == false)
+
+ if (remove_backups == false)
return a == b;
- else {
- if (!ConstString::Equals(a.m_filename, b.m_filename, case_sensitive))
- return false;
- if (ConstString::Equals(a.m_directory, b.m_directory, case_sensitive))
- return true;
- ConstString a_without_dots;
- ConstString b_without_dots;
- RemoveBackupDots(a.m_directory, a_without_dots);
- RemoveBackupDots(b.m_directory, b_without_dots);
- return ConstString::Equals(a_without_dots, b_without_dots, case_sensitive);
- }
-}
+ if (a == b)
+ return true;
-void FileSpec::NormalizePath() {
- ConstString normalized_directory;
- FileSpec::RemoveBackupDots(m_directory, normalized_directory);
- m_directory = normalized_directory;
+ return Equal(a.GetNormalizedPath(), b.GetNormalizedPath(), full, false);
}
-void FileSpec::RemoveBackupDots(const ConstString &input_const_str,
- ConstString &result_const_str) {
- const char *input = input_const_str.GetCString();
- result_const_str.Clear();
- if (!input || input[0] == '\0')
- return;
+FileSpec FileSpec::GetNormalizedPath() const {
+ // Fast path. Do nothing if the path is not interesting.
+ if (!m_directory.GetStringRef().contains(".") &&
+ (m_filename.GetStringRef() != ".." && m_filename.GetStringRef() != "."))
+ return *this;
- const char win_sep = '\\';
- const char unix_sep = '/';
- char found_sep;
- const char *win_backup = "\\..";
- const char *unix_backup = "/..";
-
- bool is_win = false;
-
- // Determine the platform for the path (win or unix):
-
- if (input[0] == win_sep)
- is_win = true;
- else if (input[0] == unix_sep)
- is_win = false;
- else if (input[1] == ':')
- is_win = true;
- else if (strchr(input, unix_sep) != nullptr)
- is_win = false;
- else if (strchr(input, win_sep) != nullptr)
- is_win = true;
- else {
- // No separators at all, no reason to do any work here.
- result_const_str = input_const_str;
- return;
- }
+ llvm::SmallString<64> path, result;
+ const bool normalize = false;
+ GetPath(path, normalize);
+ llvm::StringRef rest(path);
- llvm::StringRef backup_sep;
- if (is_win) {
- found_sep = win_sep;
- backup_sep = win_backup;
+ // We will not go below root dir.
+ size_t root_dir_start = RootDirStart(path, m_syntax);
+ const bool absolute = root_dir_start != llvm::StringRef::npos;
+ if (absolute) {
+ result += rest.take_front(root_dir_start + 1);
+ rest = rest.drop_front(root_dir_start + 1);
} else {
- found_sep = unix_sep;
- backup_sep = unix_backup;
+ if (m_syntax == ePathSyntaxWindows && path.size() > 2 && path[1] == ':') {
+ result += rest.take_front(2);
+ rest = rest.drop_front(2);
+ }
}
- llvm::StringRef input_ref(input);
- llvm::StringRef curpos(input);
-
- bool had_dots = false;
- std::string result;
-
- while (1) {
- // Start of loop
- llvm::StringRef before_sep;
- std::pair<llvm::StringRef, llvm::StringRef> around_sep =
- curpos.split(backup_sep);
-
- before_sep = around_sep.first;
- curpos = around_sep.second;
-
- if (curpos.empty()) {
- if (had_dots) {
- while (before_sep.startswith("//"))
- before_sep = before_sep.substr(1);
- if (!before_sep.empty()) {
- result.append(before_sep.data(), before_sep.size());
- }
- }
- break;
+ bool anything_added = false;
+ llvm::SmallVector<llvm::StringRef, 0> components, processed;
+ rest.split(components, '/', -1, false);
+ processed.reserve(components.size());
+ for (auto component : components) {
+ if (component == ".")
+ continue; // Skip these.
+ if (component != "..") {
+ processed.push_back(component);
+ continue; // Regular file name.
}
- had_dots = true;
-
- unsigned num_backups = 1;
- while (curpos.startswith(backup_sep)) {
- num_backups++;
- curpos = curpos.slice(backup_sep.size(), curpos.size());
+ if (!processed.empty()) {
+ processed.pop_back();
+ continue; // Dots. Go one level up if we can.
}
+ if (absolute)
+ continue; // We're at the top level. Cannot go higher than that. Skip.
- size_t end_pos = before_sep.size();
- while (num_backups-- > 0) {
- end_pos = before_sep.rfind(found_sep, end_pos);
- if (end_pos == llvm::StringRef::npos) {
- result_const_str = input_const_str;
- return;
- }
- }
- result.append(before_sep.data(), end_pos);
+ result += component; // We're a relative path. We need to keep these.
+ result += '/';
+ anything_added = true;
}
+ for (auto component : processed) {
+ result += component;
+ result += '/';
+ anything_added = true;
+ }
+ if (anything_added)
+ result.pop_back(); // Pop last '/'.
+ else if (result.empty())
+ result = ".";
- if (had_dots)
- result_const_str.SetCString(result.c_str());
- else
- result_const_str = input_const_str;
-
- return;
+ return FileSpec(result, false, m_syntax);
}
//------------------------------------------------------------------
OpenPOWER on IntegriCloud