/// Remove '.' path components from the given absolute path. /// \return \c true if any changes were made. // FIXME: Move this to llvm::sys::path. bool FileManager::removeDotPaths(SmallVectorImpl<char> &Path) { using namespace llvm::sys; SmallVector<StringRef, 16> ComponentStack; StringRef P(Path.data(), Path.size()); // Skip the root path, then look for traversal in the components. StringRef Rel = path::relative_path(P); bool AnyDots = false; for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) { if (C == ".") { AnyDots = true; continue; } ComponentStack.push_back(C); } if (!AnyDots) return false; SmallString<256> Buffer = path::root_path(P); for (StringRef C : ComponentStack) path::append(Buffer, C); Path.swap(Buffer); return true; }
/// Remove traversal (ie, . or ..) from the given absolute path. static void removePathTraversal(SmallVectorImpl<char> &Path) { using namespace llvm::sys; SmallVector<StringRef, 16> ComponentStack; StringRef P(Path.data(), Path.size()); // Skip the root path, then look for traversal in the components. StringRef Rel = path::relative_path(P); for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) { if (C == ".") continue; if (C == "..") { assert(ComponentStack.size() && "Path traverses out of parent"); ComponentStack.pop_back(); } else ComponentStack.push_back(C); } // The stack is now the path without any directory traversal. SmallString<256> Buffer = path::root_path(P); for (StringRef C : ComponentStack) path::append(Buffer, C); // Put the result in Path. Path.swap(Buffer); }
/// Remove '.' and '..' path components from the given absolute path. /// \return \c true if any changes were made. // FIXME: Move this to llvm::sys::path. bool FileManager::removeDotPaths(SmallVectorImpl<char> &Path, bool RemoveDotDot) { using namespace llvm::sys; SmallVector<StringRef, 16> ComponentStack; StringRef P(Path.data(), Path.size()); // Skip the root path, then look for traversal in the components. StringRef Rel = path::relative_path(P); for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) { if (C == ".") continue; if (RemoveDotDot) { if (C == "..") { if (!ComponentStack.empty()) ComponentStack.pop_back(); continue; } } ComponentStack.push_back(C); } SmallString<256> Buffer = path::root_path(P); for (StringRef C : ComponentStack) path::append(Buffer, C); bool Changed = (Path != Buffer); Path.swap(Buffer); return Changed; }
bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot, Style style) { StringRef p(path.data(), path.size()); SmallString<256> result = remove_dots(p, remove_dot_dot, style); if (result == path) return false; path.swap(result); return true; }
void replace_path_prefix(SmallVectorImpl<char> &Path, const StringRef &OldPrefix, const StringRef &NewPrefix, Style style) { if (OldPrefix.empty() && NewPrefix.empty()) return; StringRef OrigPath(Path.begin(), Path.size()); if (!OrigPath.startswith(OldPrefix)) return; // If prefixes have the same size we can simply copy the new one over. if (OldPrefix.size() == NewPrefix.size()) { std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin()); return; } StringRef RelPath = OrigPath.substr(OldPrefix.size()); SmallString<256> NewPath; path::append(NewPath, style, NewPrefix); path::append(NewPath, style, RelPath); Path.swap(NewPath); }