//===--- HeaderMap.h - A file that acts like dir of symlinks ----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the HeaderMap interface. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_HEADERMAP_H #define LLVM_CLANG_LEX_HEADERMAP_H #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Lex/HeaderMapTypes.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include #include namespace clang { struct HMapBucket; struct HMapHeader; /// Implementation for \a HeaderMap that doesn't depend on \a FileManager. class HeaderMapImpl { std::unique_ptr FileBuffer; bool NeedsBSwap; mutable llvm::StringMap ReverseMap; public: HeaderMapImpl(std::unique_ptr File, bool NeedsBSwap) : FileBuffer(std::move(File)), NeedsBSwap(NeedsBSwap) {} // Check for a valid header and extract the byte swap. static bool checkHeader(const llvm::MemoryBuffer &File, bool &NeedsByteSwap); // Make a call for every Key in the map. template void forEachKey(Func Callback) const { const HMapHeader &Hdr = getHeader(); unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets); for (unsigned Bucket = 0; Bucket < NumBuckets; ++Bucket) { HMapBucket B = getBucket(Bucket); if (B.Key != HMAP_EmptyBucketKey) if (std::optional Key = getString(B.Key)) Callback(*Key); } } /// If the specified relative filename is located in this HeaderMap return /// the filename it is mapped to, otherwise return an empty StringRef. StringRef lookupFilename(StringRef Filename, SmallVectorImpl &DestPath) const; /// Return the filename of the headermap. StringRef getFileName() const; /// Print the contents of this headermap to stderr. void dump() const; /// Return key for specifed path. StringRef reverseLookupFilename(StringRef DestPath) const; private: unsigned getEndianAdjustedWord(unsigned X) const; const HMapHeader &getHeader() const; HMapBucket getBucket(unsigned BucketNo) const; /// Look up the specified string in the string table. If the string index is /// not valid, return std::nullopt. std::optional getString(unsigned StrTabIdx) const; }; /// This class represents an Apple concept known as a 'header map'. To the /// \#include file resolution process, it basically acts like a directory of /// symlinks to files. Its advantages are that it is dense and more efficient /// to create and process than a directory of symlinks. class HeaderMap : private HeaderMapImpl { HeaderMap(std::unique_ptr File, bool BSwap) : HeaderMapImpl(std::move(File), BSwap) {} public: /// This attempts to load the specified file as a header map. If it doesn't /// look like a HeaderMap, it gives up and returns null. static std::unique_ptr Create(const FileEntry *FE, FileManager &FM); using HeaderMapImpl::dump; using HeaderMapImpl::forEachKey; using HeaderMapImpl::getFileName; using HeaderMapImpl::lookupFilename; using HeaderMapImpl::reverseLookupFilename; }; } // end namespace clang. #endif