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