diff options
author | Michael J. Spencer <bigcheesegs@gmail.com> | 2010-11-30 23:28:07 +0000 |
---|---|---|
committer | Michael J. Spencer <bigcheesegs@gmail.com> | 2010-11-30 23:28:07 +0000 |
commit | a42cf73c779fe4210cedce0a7a0b2ada2085b55b (patch) | |
tree | eff4e99d7db5a9672f24b36ee230abff15cce1af /lib/Support/PathV2.cpp | |
parent | 63c133b67d61b0c457ff46c957aed2b8d90b599c (diff) |
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.cpp | 123 |
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); +} + } } } |