Home | History | Annotate | Line # | Download | only in IndexSerialization
      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