summaryrefslogtreecommitdiff
path: root/lib/Support/PathV2.cpp
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2010-11-30 23:28:07 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2010-11-30 23:28:07 +0000
commita42cf73c779fe4210cedce0a7a0b2ada2085b55b (patch)
treeeff4e99d7db5a9672f24b36ee230abff15cce1af /lib/Support/PathV2.cpp
parent63c133b67d61b0c457ff46c957aed2b8d90b599c (diff)
downloadllvm-a42cf73c779fe4210cedce0a7a0b2ada2085b55b.tar.gz
llvm-a42cf73c779fe4210cedce0a7a0b2ada2085b55b.tar.bz2
llvm-a42cf73c779fe4210cedce0a7a0b2ada2085b55b.tar.xz
Support/PathV2: Implement reverse iteration and parent_path.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120496 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/PathV2.cpp')
-rw-r--r--lib/Support/PathV2.cpp123
1 files changed, 115 insertions, 8 deletions
diff --git a/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp
index 115f29447e..a97f3ec711 100644
--- a/lib/Support/PathV2.cpp
+++ b/lib/Support/PathV2.cpp
@@ -82,6 +82,78 @@ namespace {
return StringRef();
}
+
+ size_t filename_pos(const StringRef &str) {
+ if (str.size() == 2 &&
+ is_separator(str[0]) &&
+ is_separator(str[1]))
+ return 0;
+
+ if (str.size() > 0 && is_separator(str[str.size() - 1]))
+ return str.size() - 1;
+
+ size_t pos = str.find_last_of(separators, str.size() - 1);
+
+#ifdef LLVM_ON_WIN32
+ if (pos == StringRef::npos)
+ pos = str.find_last_of(':', str.size() - 2);
+#endif
+
+ if (pos == StringRef::npos ||
+ (pos == 1 && is_separator(str[0])))
+ return 0;
+
+ return pos + 1;
+ }
+
+ size_t root_dir_start(const StringRef &str) {
+ // case "c:/"
+#ifdef LLVM_ON_WIN32
+ if (str.size() > 2 &&
+ str[1] == ':' &&
+ is_separator(str[2]))
+ return 2;
+#endif
+
+ // case "//"
+ if (str.size() == 2 &&
+ is_separator(str[0]) &&
+ str[0] == str[1])
+ return StringRef::npos;
+
+ // case "//net"
+ if (str.size() > 3 &&
+ is_separator(str[0]) &&
+ str[0] == str[1] &&
+ !is_separator(str[2])) {
+ return str.find_first_of(separators, 2);
+ }
+
+ // case "/"
+ if (str.size() > 0 && is_separator(str[0]))
+ return 0;
+
+ return StringRef::npos;
+ }
+
+ size_t parent_path_end(const StringRef &path) {
+ size_t end_pos = filename_pos(path);
+
+ 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));
+
+ while(end_pos > 0 &&
+ (end_pos - 1) != root_dir_pos &&
+ is_separator(path[end_pos - 1]))
+ --end_pos;
+
+ if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
+ return StringRef::npos;
+
+ return end_pos;
+ }
}
namespace llvm {
@@ -103,14 +175,6 @@ const_iterator end(const StringRef &path) {
return i;
}
-const_iterator::reference const_iterator::operator*() const {
- return Component;
-}
-
-const_iterator::pointer const_iterator::operator->() const {
- return &Component;
-}
-
const_iterator &const_iterator::operator++() {
assert(Position < Path.size() && "Tried to increment past end!");
@@ -166,6 +230,36 @@ const_iterator &const_iterator::operator++() {
return *this;
}
+const_iterator &const_iterator::operator--() {
+ // If we're at the end and the previous char was a '/', return '.'.
+ if (Position == Path.size() &&
+ Path.size() > 1 &&
+ is_separator(Path[Position - 1])
+#ifdef LLVM_ON_WIN32
+ && Path[Position - 2] != ':'
+#endif
+ ) {
+ --Position;
+ Component = ".";
+ return *this;
+ }
+
+ // Skip separators unless it's the root directory.
+ size_t root_dir_pos = root_dir_start(Path);
+ size_t end_pos = Position;
+
+ while(end_pos > 0 &&
+ (end_pos - 1) != root_dir_pos &&
+ is_separator(Path[end_pos - 1]))
+ --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);
+ Position = start_pos;
+ return *this;
+}
+
bool const_iterator::operator==(const const_iterator &RHS) const {
return Path.begin() == RHS.Path.begin() &&
Position == RHS.Position;
@@ -175,6 +269,10 @@ bool const_iterator::operator!=(const const_iterator &RHS) const {
return !(*this == RHS);
}
+ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
+ return Position - RHS.Position;
+}
+
error_code root_path(const StringRef &path, StringRef &result) {
const_iterator b = begin(path),
pos = b,
@@ -396,6 +494,15 @@ error_code make_absolute(SmallVectorImpl<char> &path) {
"occurred above!");
}
+error_code parent_path(const StringRef &path, StringRef &result) {
+ size_t end_pos = parent_path_end(path);
+ if (end_pos == StringRef::npos)
+ result = StringRef();
+ else
+ result = StringRef(path.data(), end_pos);
+ return make_error_code(errc::success);
+}
+
}
}
}