#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 = "\\/";
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.
#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
!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) {
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 &&
return end_pos;
}
-}
+} // end unnamed namespace
namespace llvm {
namespace sys {
|| Component.endswith(":")
#endif
) {
- Component = StringRef(Path.begin() + Position, 1);
+ Component = Path.substr(Position, 1);
return *this;
}
// 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;
}
--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;
}
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;
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,
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());
}
}
+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) {
(fname.size() == 2 && fname == ".."))
return fname;
else
- return StringRef(fname.begin(), pos);
+ return fname.substr(0, pos);
}
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) {
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);
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) &&
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