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