17#include "llvm/ADT/SmallString.h"
18#include "llvm/Support/Compiler.h"
19#include "llvm/Support/DataTypes.h"
20#include "llvm/Support/MathExtras.h"
21#include "llvm/Support/MemoryBuffer.h"
22#include "llvm/Support/SwapByteOrder.h"
23#include "llvm/Support/Debug.h"
34 const char *S = Str.begin(), *End = Str.end();
54 unsigned FileSize = FE->
getSize();
55 if (FileSize <=
sizeof(
HMapHeader))
return nullptr;
58 if (!FileBuffer || !*FileBuffer)
63 return std::unique_ptr<HeaderMap>(
new HeaderMap(std::move(*FileBuffer), NeedsByteSwap));
67 bool &NeedsByteSwap) {
70 const char *FileStart =
File.getBufferStart();
79 NeedsByteSwap =
false;
91 uint32_t NumBuckets = NeedsByteSwap
92 ? llvm::sys::getSwappedBytes(Header->
NumBuckets)
94 if (!llvm::isPowerOf2_32(NumBuckets))
96 if (
File.getBufferSize() <
111 return FileBuffer->getBufferIdentifier();
114unsigned HeaderMapImpl::getEndianAdjustedWord(
unsigned X)
const {
115 if (!NeedsBSwap)
return X;
116 return llvm::byteswap<uint32_t>(
X);
121const HMapHeader &HeaderMapImpl::getHeader()
const {
123 return *
reinterpret_cast<const HMapHeader*
>(FileBuffer->getBufferStart());
129HMapBucket HeaderMapImpl::getBucket(
unsigned BucketNo)
const {
130 assert(FileBuffer->getBufferSize() >=
132 "Expected bucket to be in range");
138 reinterpret_cast<const HMapBucket*
>(FileBuffer->getBufferStart() +
140 const HMapBucket *BucketPtr = BucketArray+BucketNo;
143 Result.Key = getEndianAdjustedWord(BucketPtr->
Key);
144 Result.Prefix = getEndianAdjustedWord(BucketPtr->
Prefix);
145 Result.Suffix = getEndianAdjustedWord(BucketPtr->
Suffix);
149std::optional<StringRef> HeaderMapImpl::getString(
unsigned StrTabIdx)
const {
151 StrTabIdx += getEndianAdjustedWord(getHeader().StringsOffset);
154 if (StrTabIdx >= FileBuffer->getBufferSize())
157 const char *
Data = FileBuffer->getBufferStart() + StrTabIdx;
158 unsigned MaxLen = FileBuffer->getBufferSize() - StrTabIdx;
159 unsigned Len = strnlen(
Data, MaxLen);
162 if (Len == MaxLen &&
Data[Len - 1])
165 return StringRef(
Data, Len);
175 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
177 llvm::dbgs() <<
"Header Map " <<
getFileName() <<
":\n " << NumBuckets
178 <<
", " << getEndianAdjustedWord(Hdr.
NumEntries) <<
"\n";
180 auto getStringOrInvalid = [
this](
unsigned Id) -> StringRef {
181 if (std::optional<StringRef> S = getString(
Id))
186 for (
unsigned i = 0; i != NumBuckets; ++i) {
190 StringRef Key = getStringOrInvalid(B.
Key);
191 StringRef Prefix = getStringOrInvalid(B.
Prefix);
192 StringRef Suffix = getStringOrInvalid(B.
Suffix);
193 llvm::dbgs() <<
" " << i <<
". " << Key <<
" -> '" << Prefix <<
"' '"
201 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
204 assert(llvm::isPowerOf2_32(NumBuckets) &&
"Expected power of 2");
208 HMapBucket B = getBucket(Bucket & (NumBuckets-1));
212 std::optional<StringRef> Key = getString(B.
Key);
213 if (LLVM_UNLIKELY(!Key))
215 if (!
Filename.equals_insensitive(*Key))
220 std::optional<StringRef> Prefix = getString(B.
Prefix);
221 std::optional<StringRef> Suffix = getString(B.
Suffix);
224 if (LLVM_LIKELY(Prefix && Suffix)) {
225 DestPath.append(Prefix->begin(), Prefix->end());
226 DestPath.append(Suffix->begin(), Suffix->end());
228 return StringRef(DestPath.begin(), DestPath.size());
233 if (!ReverseMap.empty())
234 return ReverseMap.lookup(DestPath);
237 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
239 for (
unsigned i = 0; i != NumBuckets; ++i) {
244 std::optional<StringRef> Key = getString(B.
Key);
245 std::optional<StringRef> Prefix = getString(B.
Prefix);
246 std::optional<StringRef> Suffix = getString(B.
Suffix);
247 if (LLVM_LIKELY(Key && Prefix && Suffix)) {
249 Buf.append(Prefix->begin(), Prefix->end());
250 Buf.append(Suffix->begin(), Suffix->end());
251 StringRef
Value(Buf.begin(), Buf.size());
252 ReverseMap[
Value] = *Key;
254 if (DestPath ==
Value)
Defines the clang::FileManager interface and associated types.
Cached information about one file (either on disk or in the virtual file system).
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const FileEntry *Entry, bool isVolatile=false, bool RequiresNullTerminator=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
@ Result
The result type of a method or function.