diff options
author | Justin Bogner <mail@justinbogner.com> | 2014-05-20 21:43:27 +0000 |
---|---|---|
committer | Justin Bogner <mail@justinbogner.com> | 2014-05-20 21:43:27 +0000 |
commit | 9c785294fb4777283e2a5d291a07b5f0e349a415 (patch) | |
tree | 51ce017b7ada8b7162dae15c39e6d4f0cc8803be /clang/lib/Basic/VirtualFileSystem.cpp | |
parent | 93ef46b02a357cd3669ad0a0e5a2f579a4601cfe (diff) | |
download | llvm-9c785294fb4777283e2a5d291a07b5f0e349a415.zip llvm-9c785294fb4777283e2a5d291a07b5f0e349a415.tar.gz llvm-9c785294fb4777283e2a5d291a07b5f0e349a415.tar.bz2 |
VirtualFileSystem: Add YAMLVFSWriter to generate VFS mapping files
This moves the logic to write a JSON VFS mapping from the C api into
VirtualFileSystem, so that we can use it internally.
No functional change.
llvm-svn: 209241
Diffstat (limited to 'clang/lib/Basic/VirtualFileSystem.cpp')
-rw-r--r-- | clang/lib/Basic/VirtualFileSystem.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp index fae6a35..24454b0 100644 --- a/clang/lib/Basic/VirtualFileSystem.cpp +++ b/clang/lib/Basic/VirtualFileSystem.cpp @@ -11,6 +11,7 @@ #include "clang/Basic/VirtualFileSystem.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -843,3 +844,118 @@ UniqueID vfs::getNextVirtualUniqueID() { // dev_t value from the OS. return UniqueID(std::numeric_limits<uint64_t>::max(), ID); } + +#ifndef NDEBUG +static bool pathHasTraversal(StringRef Path) { + using namespace llvm::sys; + for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path))) + if (Comp == "." || Comp == "..") + return true; + return false; +} +#endif + +void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) { + assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute"); + assert(sys::path::is_absolute(RealPath) && "real path not absolute"); + assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported"); + Mappings.emplace_back(VirtualPath, RealPath); +} + +ArrayRef<YAMLVFSWriter::MapEntry> +YAMLVFSWriter::printDirNodes(llvm::raw_ostream &OS, ArrayRef<MapEntry> Entries, + StringRef ParentPath, unsigned Indent) { + while (!Entries.empty()) { + const MapEntry &Entry = Entries.front(); + OS.indent(Indent) << "{\n"; + Indent += 2; + OS.indent(Indent) << "'type': 'directory',\n"; + StringRef DirName = + containedPart(ParentPath, sys::path::parent_path(Entry.VPath)); + OS.indent(Indent) + << "'name': \"" << llvm::yaml::escape(DirName) << "\",\n"; + OS.indent(Indent) << "'contents': [\n"; + Entries = printContents(OS, Entries, Indent + 2); + OS.indent(Indent) << "]\n"; + Indent -= 2; + OS.indent(Indent) << '}'; + if (Entries.empty()) { + OS << '\n'; + break; + } + StringRef NextVPath = Entries.front().VPath; + if (!containedIn(ParentPath, NextVPath)) { + OS << '\n'; + break; + } + OS << ",\n"; + } + return Entries; +} + +ArrayRef<YAMLVFSWriter::MapEntry> +YAMLVFSWriter::printContents(llvm::raw_ostream &OS, ArrayRef<MapEntry> Entries, + unsigned Indent) { + using namespace llvm::sys; + while (!Entries.empty()) { + const MapEntry &Entry = Entries.front(); + Entries = Entries.slice(1); + StringRef ParentPath = path::parent_path(Entry.VPath); + StringRef VName = path::filename(Entry.VPath); + OS.indent(Indent) << "{\n"; + Indent += 2; + OS.indent(Indent) << "'type': 'file',\n"; + OS.indent(Indent) << "'name': \"" << llvm::yaml::escape(VName) << "\",\n"; + OS.indent(Indent) << "'external-contents': \"" + << llvm::yaml::escape(Entry.RPath) << "\"\n"; + Indent -= 2; + OS.indent(Indent) << '}'; + if (Entries.empty()) { + OS << '\n'; + break; + } + StringRef NextVPath = Entries.front().VPath; + if (!containedIn(ParentPath, NextVPath)) { + OS << '\n'; + break; + } + OS << ",\n"; + if (path::parent_path(NextVPath) != ParentPath) { + Entries = printDirNodes(OS, Entries, ParentPath, Indent); + } + } + return Entries; +} + +bool YAMLVFSWriter::containedIn(StringRef Parent, StringRef Path) { + return Path.startswith(Parent); +} + +StringRef YAMLVFSWriter::containedPart(StringRef Parent, StringRef Path) { + assert(containedIn(Parent, Path)); + if (Parent.empty()) + return Path; + return Path.slice(Parent.size() + 1, StringRef::npos); +} + +void YAMLVFSWriter::write(llvm::raw_ostream &OS) { + std::sort(Mappings.begin(), Mappings.end(), + [](const MapEntry &LHS, const MapEntry &RHS) { + return LHS.VPath < RHS.VPath; + }); + + OS << "{\n" + " 'version': 0,\n"; + if (IsCaseSensitive.hasValue()) { + OS << " 'case-sensitive': '"; + if (IsCaseSensitive.getValue()) + OS << "true"; + else + OS << "false"; + OS << "',\n"; + } + OS << " 'roots': [\n"; + printDirNodes(OS, Mappings, "", 4); + OS << " ]\n" + << "}\n"; +} |