[Lldb-commits] [lldb] r215123 - Fix FileSpec to be able to understand Windows paths.

Zachary Turner zturner at google.com
Thu Aug 7 10:33:08 PDT 2014


Author: zturner
Date: Thu Aug  7 12:33:07 2014
New Revision: 215123

URL: http://llvm.org/viewvc/llvm-project?rev=215123&view=rev
Log:
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.

Modified:
    lldb/trunk/include/lldb/Host/FileSpec.h
    lldb/trunk/include/lldb/Host/Host.h
    lldb/trunk/source/Host/common/FileSpec.cpp
    lldb/trunk/source/Host/common/Host.cpp

Modified: lldb/trunk/include/lldb/Host/FileSpec.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/FileSpec.h?rev=215123&r1=215122&r2=215123&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/FileSpec.h (original)
+++ lldb/trunk/include/lldb/Host/FileSpec.h Thu Aug  7 12:33:07 2014
@@ -51,6 +51,13 @@ public:
         eFileTypeOther
     } FileType;
 
+    enum PathSyntax
+    {
+        ePathSyntaxPosix,
+        ePathSyntaxWindows,
+        ePathSyntaxHostNative
+    };
+
     FileSpec();
 
     //------------------------------------------------------------------
@@ -69,7 +76,7 @@ public:
     ///
     /// @see FileSpec::SetFile (const char *path, bool resolve)
     //------------------------------------------------------------------
-    explicit FileSpec (const char *path, bool resolve_path);
+    explicit FileSpec (const char *path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative);
 
     //------------------------------------------------------------------
     /// Copy constructor
@@ -291,6 +298,9 @@ public:
     uint64_t
     GetByteSize() const;
 
+    PathSyntax
+    GetPathSyntax() const;
+
     //------------------------------------------------------------------
     /// Directory string get accessor.
     ///
@@ -375,7 +385,7 @@ public:
     ///     still NULL terminated).
     //------------------------------------------------------------------
     size_t
-    GetPath (char *path, size_t max_path_length) const;
+    GetPath (char *path, size_t max_path_length, bool denormalize = true) const;
 
     //------------------------------------------------------------------
     /// Extract the full path to the file.
@@ -387,7 +397,7 @@ public:
     ///     concatenated.
     //------------------------------------------------------------------
     std::string
-    GetPath () const;
+    GetPath (bool denormalize = true) const;
 
     //------------------------------------------------------------------
     /// Extract the extension of the file.
@@ -559,6 +569,10 @@ public:
     //------------------------------------------------------------------
     lldb::DataBufferSP
     ReadFileContentsAsCString(Error *error_ptr = NULL);
+
+    static void Normalize(llvm::StringRef path, llvm::SmallVectorImpl<char> &result, PathSyntax syntax);
+    static void DeNormalize(llvm::StringRef path, llvm::SmallVectorImpl<char> &result, PathSyntax syntax);
+
     //------------------------------------------------------------------
     /// Change the file specified with a new path.
     ///
@@ -574,7 +588,7 @@ public:
     ///     the static FileSpec::Resolve.
     //------------------------------------------------------------------
     void
-    SetFile (const char *path, bool resolve_path);
+    SetFile (const char *path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative);
 
     bool
     IsResolved () const
@@ -709,6 +723,7 @@ protected:
     ConstString m_directory;    ///< The uniqued directory path
     ConstString m_filename;     ///< The uniqued filename path
     mutable bool m_is_resolved; ///< True if this path has been resolved.
+    PathSyntax m_syntax;        ///< The syntax that this path uses (e.g. Windows / Posix)
 };
 
 //----------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Host/Host.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Host.h?rev=215123&r1=215122&r2=215123&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/Host.h (original)
+++ lldb/trunk/include/lldb/Host/Host.h Thu Aug  7 12:33:07 2014
@@ -362,6 +362,15 @@ public:
     SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name, size_t len);
 
     //------------------------------------------------------------------
+    /// Gets the host environment's native path syntax (Windows / Posix).
+    ///
+    /// @return
+    ///     \b One of {FileSpec::ePathSyntaxWindows, FileSpec::ePathSyntaxPosix}
+    //------------------------------------------------------------------
+    static FileSpec::PathSyntax
+    GetHostPathSyntax();
+
+    //------------------------------------------------------------------
     /// Gets the FileSpec of the user profile directory.  On Posix-platforms
     /// this is ~, and on windows this is generally something like
     /// C:\Users\Alice.

Modified: lldb/trunk/source/Host/common/FileSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/FileSpec.cpp?rev=215123&r1=215122&r2=215123&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/FileSpec.cpp (original)
+++ lldb/trunk/source/Host/common/FileSpec.cpp Thu Aug  7 12:33:07 2014
@@ -229,7 +229,8 @@ FileSpec::Resolve (const char *src_path,
 
 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,
 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,
                 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

Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=215123&r1=215122&r2=215123&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Thu Aug  7 12:33:07 2014
@@ -839,6 +839,16 @@ Host::SetShortThreadName (lldb::pid_t pi
 
 #endif
 
+FileSpec::PathSyntax
+Host::GetHostPathSyntax()
+{
+#if defined(_WIN32)
+    return FileSpec::ePathSyntaxWindows;
+#else
+    return FileSpec::ePathSyntaxPosix;
+#endif
+}
+
 FileSpec
 Host::GetUserProfileFileSpec ()
 {





More information about the lldb-commits mailing list