PTX: Fix Emacs renaming a symbol
[oota-llvm.git] / lib / Support / PathV2.cpp
index 2a4c4588a35046292154f8389a366b80b650bd79..896c94c071bcaa6acf792daca6498b43eccabd30 100644 (file)
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cctype>
+#include <cstdio>
+#include <cstring>
 
 namespace {
   using llvm::StringRef;
-
-  bool is_separator(const char value) {
-    switch(value) {
-#ifdef LLVM_ON_WIN32
-    case '\\': // fall through
-#endif
-    case '/': return true;
-    default: return false;
-    }
-  }
+  using llvm::sys::path::is_separator;
 
 #ifdef LLVM_ON_WIN32
   const StringRef separators = "\\/";
@@ -39,7 +32,7 @@ namespace {
 
   const llvm::error_code success;
 
-  StringRef find_first_component(const StringRef  &path) {
+  StringRef find_first_component(StringRef path) {
     // Look for this first component in the following order.
     // * empty (in this case we return an empty string)
     // * either C: or {//,\\}net.
@@ -53,7 +46,7 @@ namespace {
 #ifdef LLVM_ON_WIN32
     // C:
     if (path.size() >= 2 && std::isalpha(path[0]) && path[1] == ':')
-      return StringRef(path.begin(), 2);
+      return path.substr(0, 2);
 #endif
 
     // //net
@@ -63,30 +56,22 @@ namespace {
         !is_separator(path[2])) {
       // Find the next directory separator.
       size_t end = path.find_first_of(separators, 2);
-      if (end == StringRef::npos)
-        return path;
-      else
-        return StringRef(path.begin(), end);
+      return path.substr(0, end);
     }
 
     // {/,\}
     if (is_separator(path[0]))
-      return StringRef(path.begin(), 1);
+      return path.substr(0, 1);
 
     if (path.startswith(".."))
-      return StringRef(path.begin(), 2);
+      return path.substr(0, 2);
 
     if (path[0] == '.')
-      return StringRef(path.begin(), 1);
+      return path.substr(0, 1);
 
     // * {file,directory}name
     size_t end = path.find_first_of(separators, 2);
-    if (end == StringRef::npos)
-      return path;
-    else
-      return StringRef(path.begin(), end);
-
-    return StringRef();
+    return path.substr(0, end);
   }
 
   size_t filename_pos(StringRef str) {
@@ -148,7 +133,7 @@ namespace {
     bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]);
 
     // Skip separators except for root dir.
-    size_t root_dir_pos = root_dir_start(StringRef(path.begin(), end_pos));
+    size_t root_dir_pos = root_dir_start(path.substr(0, end_pos));
 
     while(end_pos > 0 &&
           (end_pos - 1) != root_dir_pos &&
@@ -160,7 +145,7 @@ namespace {
 
     return end_pos;
   }
-}
+} // end unnamed namespace
 
 namespace llvm {
 namespace sys  {
@@ -209,7 +194,7 @@ const_iterator &const_iterator::operator++() {
         || Component.endswith(":")
 #endif
         ) {
-      Component = StringRef(Path.begin() + Position, 1);
+      Component = Path.substr(Position, 1);
       return *this;
     }
 
@@ -229,9 +214,7 @@ const_iterator &const_iterator::operator++() {
 
   // Find next component.
   size_t end_pos = Path.find_first_of(separators, Position);
-  if (end_pos == StringRef::npos)
-    end_pos = Path.size();
-  Component = StringRef(Path.begin() + Position, end_pos - Position);
+  Component = Path.slice(Position, end_pos);
 
   return *this;
 }
@@ -260,8 +243,8 @@ const_iterator &const_iterator::operator--() {
     --end_pos;
 
   // Find next separator.
-  size_t start_pos = filename_pos(StringRef(Path.begin(), end_pos));
-  Component = StringRef(Path.begin() + start_pos, end_pos - start_pos);
+  size_t start_pos = filename_pos(Path.substr(0, end_pos));
+  Component = Path.slice(start_pos, end_pos);
   Position = start_pos;
   return *this;
 }
@@ -295,7 +278,7 @@ const StringRef root_path(StringRef path) {
     if (has_net || has_drive) {
       if ((++pos != e) && is_separator((*pos)[0])) {
         // {C:/,//net/}, so get the first two components.
-        return StringRef(path.begin(), b->size() + pos->size());
+        return path.substr(0, b->size() + pos->size());
       } else {
         // just {C:,//net}, return the first component.
         return *b;
@@ -364,7 +347,7 @@ const StringRef root_directory(StringRef path) {
 
 const StringRef relative_path(StringRef path) {
   StringRef root = root_path(path);
-  return StringRef(path.begin() + root.size(), path.size() - root.size());
+  return root.substr(root.size());
 }
 
 void append(SmallVectorImpl<char> &path, const Twine &a,
@@ -392,7 +375,7 @@ void append(SmallVectorImpl<char> &path, const Twine &a,
     if (path_has_sep) {
       // Strip separators from beginning of component.
       size_t loc = i->find_first_not_of(separators);
-      StringRef c = StringRef(i->begin() + loc, i->size() - loc);
+      StringRef c = i->substr(loc);
 
       // Append it.
       path.append(c.begin(), c.end());
@@ -408,12 +391,18 @@ void append(SmallVectorImpl<char> &path, const Twine &a,
   }
 }
 
+void append(SmallVectorImpl<char> &path,
+            const_iterator begin, const_iterator end) {
+  for (; begin != end; ++begin)
+    path::append(path, *begin);
+}
+
 const StringRef parent_path(StringRef path) {
   size_t end_pos = parent_path_end(path);
   if (end_pos == StringRef::npos)
     return StringRef();
   else
-    return StringRef(path.data(), end_pos);
+    return path.substr(0, end_pos);
 }
 
 void remove_filename(SmallVectorImpl<char> &path) {
@@ -475,7 +464,7 @@ const StringRef stem(StringRef path) {
         (fname.size() == 2 && fname == ".."))
       return fname;
     else
-      return StringRef(fname.begin(), pos);
+      return fname.substr(0, pos);
 }
 
 const StringRef extension(StringRef path) {
@@ -488,7 +477,17 @@ const StringRef extension(StringRef path) {
         (fname.size() == 2 && fname == ".."))
       return StringRef();
     else
-      return StringRef(fname.begin() + pos, fname.size() - pos);
+      return fname.substr(pos);
+}
+
+bool is_separator(char value) {
+  switch(value) {
+#ifdef LLVM_ON_WIN32
+    case '\\': // fall through
+#endif
+    case '/': return true;
+    default: return false;
+  }
 }
 
 bool has_root_name(const Twine &path) {
@@ -512,6 +511,13 @@ bool has_root_path(const Twine &path) {
   return !root_path(p).empty();
 }
 
+bool has_relative_path(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !relative_path(p).empty();
+}
+
 bool has_filename(const Twine &path) {
   SmallString<128> path_storage;
   StringRef p = path.toStringRef(path_storage);
@@ -637,14 +643,38 @@ bool is_directory(file_status status) {
   return status.type() == file_type::directory_file;
 }
 
+error_code is_directory(const Twine &path, bool &result) {
+  file_status st;
+  if (error_code ec = status(path, st))
+    return ec;
+  result = is_directory(st);
+  return success;
+}
+
 bool is_regular_file(file_status status) {
   return status.type() == file_type::regular_file;
 }
 
+error_code is_regular_file(const Twine &path, bool &result) {
+  file_status st;
+  if (error_code ec = status(path, st))
+    return ec;
+  result = is_regular_file(st);
+  return success;
+}
+
 bool is_symlink(file_status status) {
   return status.type() == file_type::symlink_file;
 }
 
+error_code is_symlink(const Twine &path, bool &result) {
+  file_status st;
+  if (error_code ec = status(path, st))
+    return ec;
+  result = is_symlink(st);
+  return success;
+}
+
 bool is_other(file_status status) {
   return exists(status) &&
          !is_regular_file(status) &&
@@ -662,6 +692,75 @@ void directory_entry::replace_filename(const Twine &filename, file_status st,
   SymlinkStatus = symlink_st;
 }
 
+error_code has_magic(const Twine &path, const Twine &magic, bool &result) {
+  SmallString<32>  MagicStorage;
+  StringRef Magic = magic.toStringRef(MagicStorage);
+  SmallString<32> Buffer;
+
+  if (error_code ec = get_magic(path, Magic.size(), Buffer)) {
+    if (ec == errc::value_too_large) {
+      // Magic.size() > file_size(Path).
+      result = false;
+      return success;
+    }
+    return ec;
+  }
+
+  result = Magic == Buffer;
+  return success;
+}
+
+error_code identify_magic(const Twine &path, LLVMFileType &result) {
+  SmallString<32> Magic;
+  error_code ec = get_magic(path, Magic.capacity(), Magic);
+  if (ec && ec != errc::value_too_large)
+    return ec;
+
+  result = IdentifyFileType(Magic.data(), Magic.size());
+  return success;
+}
+
+namespace {
+error_code remove_all_r(StringRef path, file_type ft, uint32_t &count) {
+  if (ft == file_type::directory_file) {
+    // This code would be a lot better with exceptions ;/.
+    error_code ec;
+    for (directory_iterator i(path, ec), e; i != e; i.increment(ec)) {
+      if (ec) return ec;
+      file_status st;
+      if (error_code ec = i->status(st)) return ec;
+      if (error_code ec = remove_all_r(i->path(), st.type(), count)) return ec;
+    }
+    bool obviously_this_exists;
+    if (error_code ec = remove(path, obviously_this_exists)) return ec;
+    assert(obviously_this_exists);
+    ++count; // Include the directory itself in the items removed.
+  } else {
+    bool obviously_this_exists;
+    if (error_code ec = remove(path, obviously_this_exists)) return ec;
+    assert(obviously_this_exists);
+    ++count;
+  }
+
+  return success;
+}
+} // end unnamed namespace
+
+error_code remove_all(const Twine &path, uint32_t &num_removed) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  file_status fs;
+  if (error_code ec = status(path, fs))
+    return ec;
+  num_removed = 0;
+  return remove_all_r(p, fs.type(), num_removed);
+}
+
+error_code directory_entry::status(file_status &result) const {
+  return fs::status(Path, result);
+}
+
 } // end namespace fs
 } // end namespace sys
 } // end namespace llvm