xref: /llvm-project/clang/unittests/Lex/HeaderMapTestUtils.h (revision f435f55d58542ecde0e66460555ccbcbca355cc5)
137b530a2SDmitry Polukhin //===- unittests/Lex/HeaderMapTestUtils.h - HeaderMap utils -------===//
237b530a2SDmitry Polukhin //
337b530a2SDmitry Polukhin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
437b530a2SDmitry Polukhin // See https://llvm.org/LICENSE.txt for license information.
537b530a2SDmitry Polukhin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
637b530a2SDmitry Polukhin //
737b530a2SDmitry Polukhin //===--------------------------------------------------------------===//
837b530a2SDmitry Polukhin 
937b530a2SDmitry Polukhin #ifndef LLVM_CLANG_UNITTESTS_LEX_HEADERMAPTESTUTILS_H
1037b530a2SDmitry Polukhin #define LLVM_CLANG_UNITTESTS_LEX_HEADERMAPTESTUTILS_H
1137b530a2SDmitry Polukhin 
1237b530a2SDmitry Polukhin #include "clang/Basic/CharInfo.h"
1337b530a2SDmitry Polukhin #include "clang/Lex/HeaderMap.h"
1437b530a2SDmitry Polukhin #include "clang/Lex/HeaderMapTypes.h"
1537b530a2SDmitry Polukhin #include "llvm/Support/SwapByteOrder.h"
1637b530a2SDmitry Polukhin #include <cassert>
1737b530a2SDmitry Polukhin 
1837b530a2SDmitry Polukhin namespace clang {
1937b530a2SDmitry Polukhin namespace test {
2037b530a2SDmitry Polukhin 
2137b530a2SDmitry Polukhin // Lay out a header file for testing.
2237b530a2SDmitry Polukhin template <unsigned NumBuckets, unsigned NumBytes> struct HMapFileMock {
2337b530a2SDmitry Polukhin   HMapHeader Header;
2437b530a2SDmitry Polukhin   HMapBucket Buckets[NumBuckets];
2537b530a2SDmitry Polukhin   unsigned char Bytes[NumBytes];
2637b530a2SDmitry Polukhin 
initHMapFileMock2737b530a2SDmitry Polukhin   void init() {
2837b530a2SDmitry Polukhin     memset(this, 0, sizeof(HMapFileMock));
2937b530a2SDmitry Polukhin     Header.Magic = HMAP_HeaderMagicNumber;
3037b530a2SDmitry Polukhin     Header.Version = HMAP_HeaderVersion;
3137b530a2SDmitry Polukhin     Header.NumBuckets = NumBuckets;
3237b530a2SDmitry Polukhin     Header.StringsOffset = sizeof(Header) + sizeof(Buckets);
3337b530a2SDmitry Polukhin   }
3437b530a2SDmitry Polukhin 
swapBytesHMapFileMock3537b530a2SDmitry Polukhin   void swapBytes() {
36*f435f55dSKazu Hirata     Header.Magic = llvm::byteswap(Header.Magic);
37*f435f55dSKazu Hirata     Header.Version = llvm::byteswap(Header.Version);
38*f435f55dSKazu Hirata     Header.NumBuckets = llvm::byteswap(Header.NumBuckets);
39*f435f55dSKazu Hirata     Header.StringsOffset = llvm::byteswap(Header.StringsOffset);
4037b530a2SDmitry Polukhin   }
4137b530a2SDmitry Polukhin 
getBufferHMapFileMock4237b530a2SDmitry Polukhin   std::unique_ptr<llvm::MemoryBuffer> getBuffer() {
4337b530a2SDmitry Polukhin     return llvm::MemoryBuffer::getMemBuffer(
4437b530a2SDmitry Polukhin         StringRef(reinterpret_cast<char *>(this), sizeof(HMapFileMock)),
4537b530a2SDmitry Polukhin         "header",
4637b530a2SDmitry Polukhin         /* RequresNullTerminator */ false);
4737b530a2SDmitry Polukhin   }
4837b530a2SDmitry Polukhin };
4937b530a2SDmitry Polukhin 
5037b530a2SDmitry Polukhin template <class FileTy> struct HMapFileMockMaker {
5137b530a2SDmitry Polukhin   FileTy &File;
5237b530a2SDmitry Polukhin   unsigned SI = 1;
5337b530a2SDmitry Polukhin   unsigned BI = 0;
HMapFileMockMakerHMapFileMockMaker5437b530a2SDmitry Polukhin   HMapFileMockMaker(FileTy &File) : File(File) {}
5537b530a2SDmitry Polukhin 
addStringHMapFileMockMaker5637b530a2SDmitry Polukhin   unsigned addString(StringRef S) {
5737b530a2SDmitry Polukhin     assert(SI + S.size() + 1 <= sizeof(File.Bytes));
5837b530a2SDmitry Polukhin     std::copy(S.begin(), S.end(), File.Bytes + SI);
5937b530a2SDmitry Polukhin     auto OldSI = SI;
6037b530a2SDmitry Polukhin     SI += S.size() + 1;
6137b530a2SDmitry Polukhin     return OldSI;
6237b530a2SDmitry Polukhin   }
6337b530a2SDmitry Polukhin 
addBucketHMapFileMockMaker6437b530a2SDmitry Polukhin   void addBucket(StringRef Str, unsigned Key, unsigned Prefix,
6537b530a2SDmitry Polukhin                  unsigned Suffix) {
6637b530a2SDmitry Polukhin     addBucket(getHash(Str), Key, Prefix, Suffix);
6737b530a2SDmitry Polukhin   }
6837b530a2SDmitry Polukhin 
addBucketHMapFileMockMaker6937b530a2SDmitry Polukhin   void addBucket(unsigned Hash, unsigned Key, unsigned Prefix,
7037b530a2SDmitry Polukhin                  unsigned Suffix) {
7137b530a2SDmitry Polukhin     assert(!(File.Header.NumBuckets & (File.Header.NumBuckets - 1)));
7237b530a2SDmitry Polukhin     unsigned I = Hash & (File.Header.NumBuckets - 1);
7337b530a2SDmitry Polukhin     do {
7437b530a2SDmitry Polukhin       if (!File.Buckets[I].Key) {
7537b530a2SDmitry Polukhin         File.Buckets[I].Key = Key;
7637b530a2SDmitry Polukhin         File.Buckets[I].Prefix = Prefix;
7737b530a2SDmitry Polukhin         File.Buckets[I].Suffix = Suffix;
7837b530a2SDmitry Polukhin         ++File.Header.NumEntries;
7937b530a2SDmitry Polukhin         return;
8037b530a2SDmitry Polukhin       }
8137b530a2SDmitry Polukhin       ++I;
8237b530a2SDmitry Polukhin       I &= File.Header.NumBuckets - 1;
8337b530a2SDmitry Polukhin     } while (I != (Hash & (File.Header.NumBuckets - 1)));
8437b530a2SDmitry Polukhin     llvm_unreachable("no empty buckets");
8537b530a2SDmitry Polukhin   }
8637b530a2SDmitry Polukhin 
8737b530a2SDmitry Polukhin   // The header map hash function.
getHashHMapFileMockMaker8837b530a2SDmitry Polukhin   static unsigned getHash(StringRef Str) {
8937b530a2SDmitry Polukhin     unsigned Result = 0;
9037b530a2SDmitry Polukhin     for (char C : Str)
9137b530a2SDmitry Polukhin       Result += toLowercase(C) * 13;
9237b530a2SDmitry Polukhin     return Result;
9337b530a2SDmitry Polukhin   }
9437b530a2SDmitry Polukhin };
9537b530a2SDmitry Polukhin 
9637b530a2SDmitry Polukhin } // namespace test
9737b530a2SDmitry Polukhin } // namespace clang
9837b530a2SDmitry Polukhin 
9937b530a2SDmitry Polukhin #endif
100