1 //===--- SerializablePathCollection.cpp -- Index of paths -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/IndexSerialization/SerializablePathCollection.h" 10 #include "llvm/Support/Path.h" 11 12 using namespace llvm; 13 using namespace clang; 14 using namespace clang::index; 15 16 StringPool::StringOffsetSize StringPool::add(StringRef Str) { 17 const std::size_t Offset = Buffer.size(); 18 Buffer += Str; 19 return StringPool::StringOffsetSize(Offset, Str.size()); 20 } 21 22 size_t PathPool::addFilePath(RootDirKind Root, 23 const StringPool::StringOffsetSize &Dir, 24 StringRef Filename) { 25 FilePaths.emplace_back(DirPath(Root, Dir), Paths.add(Filename)); 26 return FilePaths.size() - 1; 27 } 28 29 StringPool::StringOffsetSize PathPool::addDirPath(StringRef Dir) { 30 return Paths.add(Dir); 31 } 32 33 llvm::ArrayRef<PathPool::FilePath> PathPool::getFilePaths() const { 34 return FilePaths; 35 } 36 37 StringRef PathPool::getPaths() const { return Paths.getBuffer(); } 38 39 SerializablePathCollection::SerializablePathCollection( 40 StringRef CurrentWorkDir, StringRef SysRoot, llvm::StringRef OutputFile) 41 : WorkDir(CurrentWorkDir), 42 SysRoot(llvm::sys::path::parent_path(SysRoot).empty() ? StringRef() 43 : SysRoot), 44 WorkDirPath(Paths.addDirPath(WorkDir)), 45 SysRootPath(Paths.addDirPath(SysRoot)), 46 OutputFilePath(Paths.addDirPath(OutputFile)) {} 47 48 size_t SerializablePathCollection::tryStoreFilePath(const FileEntry &FE) { 49 auto FileIt = UniqueFiles.find(&FE); 50 if (FileIt != UniqueFiles.end()) 51 return FileIt->second; 52 53 const auto Dir = tryStoreDirPath(sys::path::parent_path(FE.getName())); 54 const auto FileIdx = 55 Paths.addFilePath(Dir.Root, Dir.Path, sys::path::filename(FE.getName())); 56 57 UniqueFiles.try_emplace(&FE, FileIdx); 58 return FileIdx; 59 } 60 61 PathPool::DirPath SerializablePathCollection::tryStoreDirPath(StringRef Dir) { 62 // We don't want to strip separator if Dir is "/" - so we check size > 1. 63 while (Dir.size() > 1 && llvm::sys::path::is_separator(Dir.back())) 64 Dir = Dir.drop_back(); 65 66 auto DirIt = UniqueDirs.find(Dir); 67 if (DirIt != UniqueDirs.end()) 68 return DirIt->second; 69 70 const std::string OrigDir = Dir.str(); 71 72 PathPool::RootDirKind Root = PathPool::RootDirKind::Regular; 73 if (!SysRoot.empty() && Dir.startswith(SysRoot) && 74 llvm::sys::path::is_separator(Dir[SysRoot.size()])) { 75 Root = PathPool::RootDirKind::SysRoot; 76 Dir = Dir.drop_front(SysRoot.size()); 77 } else if (!WorkDir.empty() && Dir.startswith(WorkDir) && 78 llvm::sys::path::is_separator(Dir[WorkDir.size()])) { 79 Root = PathPool::RootDirKind::CurrentWorkDir; 80 Dir = Dir.drop_front(WorkDir.size()); 81 } 82 83 if (Root != PathPool::RootDirKind::Regular) { 84 while (!Dir.empty() && llvm::sys::path::is_separator(Dir.front())) 85 Dir = Dir.drop_front(); 86 } 87 88 PathPool::DirPath Result(Root, Paths.addDirPath(Dir)); 89 UniqueDirs.try_emplace(OrigDir, Result); 90 return Result; 91 } 92