diff options
author | Zachary Turner <zturner@google.com> | 2014-08-07 17:33:07 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2014-08-07 17:33:07 +0000 |
commit | df62f20c75d0984aac06b8b998988eb91262e43c (patch) | |
tree | 9ae54a149637a5998f3b030aabd71cb95e7406f5 /lldb/source | |
parent | 17ae2fca4ca0bf8396af7cec68b376efcfe0e63e (diff) | |
download | bcm5719-llvm-df62f20c75d0984aac06b8b998988eb91262e43c.tar.gz bcm5719-llvm-df62f20c75d0984aac06b8b998988eb91262e43c.zip |
Fix FileSpec to be able to understand Windows paths.
This patch adds the notion of a "path syntax" to FileSpec. There
are two syntaxes (Posix and Windows) and one "meta syntax",
Host Native, which uses the current platform to figure out the
appropriate syntax for host paths.
This allows paths from one platform to be represented and
manipulated on another platform even if they have different path
syntaxes.
llvm-svn: 215123
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Host/common/FileSpec.cpp | 109 | ||||
-rw-r--r-- | lldb/source/Host/common/Host.cpp | 10 |
2 files changed, 74 insertions, 45 deletions
diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp index 44eb3af118f..845a3183001 100644 --- a/lldb/source/Host/common/FileSpec.cpp +++ b/lldb/source/Host/common/FileSpec.cpp @@ -229,7 +229,8 @@ FileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len) FileSpec::FileSpec() : m_directory(), - m_filename() + m_filename(), + m_syntax(Host::GetHostPathSyntax()) { } @@ -237,13 +238,13 @@ FileSpec::FileSpec() : // Default constructor that can take an optional full path to a // file on disk. //------------------------------------------------------------------ -FileSpec::FileSpec(const char *pathname, bool resolve_path) : +FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) : m_directory(), m_filename(), m_is_resolved(false) { if (pathname && pathname[0]) - SetFile(pathname, resolve_path); + SetFile(pathname, resolve_path, syntax); } //------------------------------------------------------------------ @@ -252,7 +253,8 @@ FileSpec::FileSpec(const char *pathname, bool resolve_path) : FileSpec::FileSpec(const FileSpec& rhs) : m_directory (rhs.m_directory), m_filename (rhs.m_filename), - m_is_resolved (rhs.m_is_resolved) + m_is_resolved (rhs.m_is_resolved), + m_syntax (rhs.m_syntax) { } @@ -285,46 +287,71 @@ FileSpec::operator= (const FileSpec& rhs) m_directory = rhs.m_directory; m_filename = rhs.m_filename; m_is_resolved = rhs.m_is_resolved; + m_syntax = rhs.m_syntax; } return *this; } +void FileSpec::Normalize(llvm::StringRef path, llvm::SmallVectorImpl<char> &result, PathSyntax syntax) +{ + result.clear(); + result.append(path.begin(), path.end()); + if (syntax == ePathSyntaxPosix || (syntax == ePathSyntaxHostNative && Host::GetHostPathSyntax() == ePathSyntaxPosix)) + return; + + std::replace(result.begin(), result.end(), '\\', '/'); +} + +void FileSpec::DeNormalize(llvm::StringRef path, llvm::SmallVectorImpl<char> &result, PathSyntax syntax) +{ + result.clear(); + result.append(path.begin(), path.end()); + if (syntax == ePathSyntaxPosix || (syntax == ePathSyntaxHostNative && Host::GetHostPathSyntax() == ePathSyntaxPosix)) + return; + + std::replace(result.begin(), result.end(), '/', '\\'); +} + //------------------------------------------------------------------ // Update the contents of this object with a new path. The path will // be split up into a directory and filename and stored as uniqued // string values for quick comparison and efficient memory usage. //------------------------------------------------------------------ void -FileSpec::SetFile (const char *pathname, bool resolve) +FileSpec::SetFile (const char *pathname, bool resolve, PathSyntax syntax) { m_filename.Clear(); m_directory.Clear(); m_is_resolved = false; + m_syntax = (syntax == ePathSyntaxHostNative) ? Host::GetHostPathSyntax() : syntax; + if (pathname == NULL || pathname[0] == '\0') return; - char resolved_path[PATH_MAX]; + llvm::SmallString<64> normalized; + Normalize(pathname, normalized, syntax); + + std::vector<char> resolved_path(PATH_MAX); bool path_fit = true; if (resolve) { - path_fit = (FileSpec::Resolve (pathname, resolved_path, sizeof(resolved_path)) < sizeof(resolved_path) - 1); + path_fit = (FileSpec::Resolve (normalized.c_str(), &resolved_path[0], resolved_path.size()) < resolved_path.size() - 1); m_is_resolved = path_fit; } else { // Copy the path because "basename" and "dirname" want to muck with the // path buffer - if (::strlen (pathname) > sizeof(resolved_path) - 1) + if (normalized.size() > resolved_path.size() - 1) path_fit = false; else - ::strcpy (resolved_path, pathname); + ::strcpy (&resolved_path[0], normalized.c_str()); } - if (path_fit) { - llvm::StringRef resolve_path_ref(resolved_path); + llvm::StringRef resolve_path_ref(&resolved_path[0]); llvm::StringRef filename_ref = llvm::sys::path::filename(resolve_path_ref); if (!filename_ref.empty()) { @@ -334,7 +361,7 @@ FileSpec::SetFile (const char *pathname, bool resolve) m_directory.SetString(directory_ref); } else - m_directory.SetCString(resolved_path); + m_directory.SetCString(&resolved_path[0]); } } @@ -580,7 +607,7 @@ FileSpec::ResolvePath () return true; // We have already resolved this path char path_buf[PATH_MAX]; - if (!GetPath (path_buf, PATH_MAX)) + if (!GetPath (path_buf, PATH_MAX, false)) return false; // SetFile(...) will set m_is_resolved correctly if it can resolve the path SetFile (path_buf, true); @@ -596,6 +623,12 @@ FileSpec::GetByteSize() const return 0; } +FileSpec::PathSyntax +FileSpec::GetPathSyntax() const +{ + return m_syntax; +} + FileSpec::FileType FileSpec::GetFileType () const { @@ -681,45 +714,31 @@ FileSpec::GetFilename() const // values. //------------------------------------------------------------------ size_t -FileSpec::GetPath(char *path, size_t path_max_len) const +FileSpec::GetPath(char *path, size_t path_max_len, bool denormalize) const { - if (path_max_len) - { - const char *dirname = m_directory.GetCString(); - const char *filename = m_filename.GetCString(); - if (dirname) - { - if (filename) - return ::snprintf (path, path_max_len, "%s/%s", dirname, filename); - else - return ::snprintf (path, path_max_len, "%s", dirname); - } - else if (filename) - { - return ::snprintf (path, path_max_len, "%s", filename); - } - } - if (path) - path[0] = '\0'; - return 0; + std::string result = GetPath(denormalize); + + size_t result_length = std::min(path_max_len-1, result.length()); + ::strncpy(path, result.c_str(), result_length + 1); + return result_length; } std::string -FileSpec::GetPath (void) const +FileSpec::GetPath (bool denormalize) const { - static ConstString g_slash_only ("/"); - std::string path; - const char *dirname = m_directory.GetCString(); - const char *filename = m_filename.GetCString(); - if (dirname) + llvm::SmallString<64> result; + if (m_directory) + result.append(m_directory.GetCString()); + if (m_filename) + llvm::sys::path::append(result, m_filename.GetCString()); + if (denormalize && !result.empty()) { - path.append (dirname); - if (filename && m_directory != g_slash_only) - path.append ("/"); + llvm::SmallString<64> denormalized; + DeNormalize(result.c_str(), denormalized, m_syntax); + result = denormalized; } - if (filename) - path.append (filename); - return path; + + return std::string(result.begin(), result.end()); } ConstString diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index df1c78726b6..a19608365ec 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -839,6 +839,16 @@ Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, #endif +FileSpec::PathSyntax +Host::GetHostPathSyntax() +{ +#if defined(_WIN32) + return FileSpec::ePathSyntaxWindows; +#else + return FileSpec::ePathSyntaxPosix; +#endif +} + FileSpec Host::GetUserProfileFileSpec () { |