1 //===--- HeaderMap.h - A file that acts like dir of symlinks ----*- 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 // This file defines the HeaderMap interface. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_LEX_HEADERMAP_H 14 #define LLVM_CLANG_LEX_HEADERMAP_H 15 16 #include "clang/Basic/FileManager.h" 17 #include "clang/Basic/LLVM.h" 18 #include "clang/Lex/HeaderMapTypes.h" 19 #include "llvm/ADT/StringMap.h" 20 #include "llvm/Support/Compiler.h" 21 #include "llvm/Support/MemoryBuffer.h" 22 #include <memory> 23 #include <optional> 24 25 namespace clang { 26 27 struct HMapBucket; 28 struct HMapHeader; 29 30 /// Implementation for \a HeaderMap that doesn't depend on \a FileManager. 31 class HeaderMapImpl { 32 std::unique_ptr<const llvm::MemoryBuffer> FileBuffer; 33 bool NeedsBSwap; 34 mutable llvm::StringMap<StringRef> ReverseMap; 35 36 public: 37 HeaderMapImpl(std::unique_ptr<const llvm::MemoryBuffer> File, bool NeedsBSwap) 38 : FileBuffer(std::move(File)), NeedsBSwap(NeedsBSwap) {} 39 40 // Check for a valid header and extract the byte swap. 41 static bool checkHeader(const llvm::MemoryBuffer &File, bool &NeedsByteSwap); 42 43 // Make a call for every Key in the map. 44 template <typename Func> void forEachKey(Func Callback) const { 45 const HMapHeader &Hdr = getHeader(); 46 unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets); 47 48 for (unsigned Bucket = 0; Bucket < NumBuckets; ++Bucket) { 49 HMapBucket B = getBucket(Bucket); 50 if (B.Key != HMAP_EmptyBucketKey) 51 if (std::optional<StringRef> Key = getString(B.Key)) 52 Callback(*Key); 53 } 54 } 55 56 /// If the specified relative filename is located in this HeaderMap return 57 /// the filename it is mapped to, otherwise return an empty StringRef. 58 StringRef lookupFilename(StringRef Filename, 59 SmallVectorImpl<char> &DestPath) const; 60 61 /// Return the filename of the headermap. 62 StringRef getFileName() const; 63 64 /// Print the contents of this headermap to stderr. 65 void dump() const; 66 67 /// Return key for specifed path. 68 StringRef reverseLookupFilename(StringRef DestPath) const; 69 70 private: 71 unsigned getEndianAdjustedWord(unsigned X) const; 72 const HMapHeader &getHeader() const; 73 HMapBucket getBucket(unsigned BucketNo) const; 74 75 /// Look up the specified string in the string table. If the string index is 76 /// not valid, return std::nullopt. 77 std::optional<StringRef> getString(unsigned StrTabIdx) const; 78 }; 79 80 /// This class represents an Apple concept known as a 'header map'. To the 81 /// \#include file resolution process, it basically acts like a directory of 82 /// symlinks to files. Its advantages are that it is dense and more efficient 83 /// to create and process than a directory of symlinks. 84 class HeaderMap : private HeaderMapImpl { 85 HeaderMap(std::unique_ptr<const llvm::MemoryBuffer> File, bool BSwap) 86 : HeaderMapImpl(std::move(File), BSwap) {} 87 88 public: 89 /// This attempts to load the specified file as a header map. If it doesn't 90 /// look like a HeaderMap, it gives up and returns null. 91 static std::unique_ptr<HeaderMap> Create(const FileEntry *FE, 92 FileManager &FM); 93 94 using HeaderMapImpl::dump; 95 using HeaderMapImpl::forEachKey; 96 using HeaderMapImpl::getFileName; 97 using HeaderMapImpl::lookupFilename; 98 using HeaderMapImpl::reverseLookupFilename; 99 }; 100 101 } // end namespace clang. 102 103 #endif 104