1 //===--- SerializablePathCollection.h -- 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 #ifndef LLVM_CLANG_INDEXSERIALIZATION_SERIALIZABLEPATHCOLLECTION_H
10 #define LLVM_CLANG_INDEXSERIALIZATION_SERIALIZABLEPATHCOLLECTION_H
11 
12 #include "clang/Basic/FileManager.h"
13 #include "llvm/ADT/APInt.h"
14 #include "llvm/ADT/DenseMap.h"
15 #include "llvm/ADT/Optional.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/iterator.h"
20 
21 #include <string>
22 #include <vector>
23 
24 namespace clang {
25 namespace index {
26 
27 /// Pool of strings
28 class StringPool {
29   llvm::SmallString<512> Buffer;
30 
31 public:
32   struct StringOffsetSize {
33     std::size_t Offset;
34     std::size_t Size;
35 
36     StringOffsetSize(size_t Offset, size_t Size) : Offset(Offset), Size(Size) {}
37   };
38 
39   StringOffsetSize add(StringRef Str);
40   StringRef getBuffer() const { return Buffer; }
41 };
42 
43 /// Pool of filesystem paths backed by a StringPool
44 class PathPool {
45 public:
46   /// Special root directory of a filesystem path.
47   enum class RootDirKind {
48     Regular = 0,
49     CurrentWorkDir = 1,
50     SysRoot = 2,
51   };
52 
53   struct DirPath {
54     RootDirKind Root;
55     StringPool::StringOffsetSize Path;
56 
57     DirPath(RootDirKind Root, const StringPool::StringOffsetSize &Path)
58         : Root(Root), Path(Path) {}
59   };
60 
61   struct FilePath {
62     DirPath Dir;
63     StringPool::StringOffsetSize Filename;
64 
65     FilePath(const DirPath &Dir, const StringPool::StringOffsetSize &Filename)
66         : Dir(Dir), Filename(Filename) {}
67   };
68 
69   /// \returns index of the newly added file in FilePaths.
70   size_t addFilePath(RootDirKind Root, const StringPool::StringOffsetSize &Dir,
71                      StringRef Filename);
72 
73   /// \returns offset in Paths and size of newly added directory.
74   StringPool::StringOffsetSize addDirPath(StringRef Dir);
75 
76   llvm::ArrayRef<FilePath> getFilePaths() const;
77 
78   StringRef getPaths() const;
79 
80 private:
81   StringPool Paths;
82   std::vector<FilePath> FilePaths;
83 };
84 
85 /// Stores file paths and produces serialization-friendly representation.
86 class SerializablePathCollection {
87   std::string WorkDir;
88   std::string SysRoot;
89 
90   PathPool Paths;
91   llvm::DenseMap<const clang::FileEntry *, std::size_t> UniqueFiles;
92   llvm::StringMap<PathPool::DirPath, llvm::BumpPtrAllocator> UniqueDirs;
93 
94 public:
95   const StringPool::StringOffsetSize WorkDirPath;
96   const StringPool::StringOffsetSize SysRootPath;
97   const StringPool::StringOffsetSize OutputFilePath;
98 
99   SerializablePathCollection(llvm::StringRef CurrentWorkDir,
100                              llvm::StringRef SysRoot,
101                              llvm::StringRef OutputFile);
102 
103   /// \returns buffer containing all the paths.
104   llvm::StringRef getPathsBuffer() const { return Paths.getPaths(); }
105 
106   /// \returns file paths (no directories) backed by buffer exposed in
107   /// getPathsBuffer.
108   ArrayRef<PathPool::FilePath> getFilePaths() const {
109     return Paths.getFilePaths();
110   }
111 
112   /// Stores path to \p FE if it hasn't been stored yet.
113   /// \returns index to array exposed by getPathsBuffer().
114   size_t tryStoreFilePath(const clang::FileEntry &FE);
115 
116 private:
117   /// Stores \p Path if it is non-empty.
118   /// Warning: this method doesn't check for uniqueness.
119   /// \returns offset of \p Path value begin in buffer with stored paths.
120   StringPool::StringOffsetSize storePath(llvm::StringRef Path);
121 
122   /// Stores \p dirStr path if it hasn't been stored yet.
123   PathPool::DirPath tryStoreDirPath(llvm::StringRef dirStr);
124 };
125 
126 } // namespace index
127 } // namespace clang
128 
129 #endif // LLVM_CLANG_INDEXSERIALIZATION_SERIALIZABLEPATHCOLLECTION_H
130