15ffd83dbSDimitry Andric //===- StringMapEntry.h - String Hash table map interface -------*- C++ -*-===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // This file defines the StringMapEntry class - it is intended to be a low 105ffd83dbSDimitry Andric // dependency implementation detail of StringMap that is more suitable for 115ffd83dbSDimitry Andric // inclusion in public headers than StringMap.h itself is. 125ffd83dbSDimitry Andric // 135ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 145ffd83dbSDimitry Andric 155ffd83dbSDimitry Andric #ifndef LLVM_ADT_STRINGMAPENTRY_H 165ffd83dbSDimitry Andric #define LLVM_ADT_STRINGMAPENTRY_H 175ffd83dbSDimitry Andric 18*04eeddc0SDimitry Andric #include "llvm/ADT/None.h" 195ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h" 20*04eeddc0SDimitry Andric #include "llvm/ADT/STLFunctionalExtras.h" 215ffd83dbSDimitry Andric 225ffd83dbSDimitry Andric namespace llvm { 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric /// StringMapEntryBase - Shared base class of StringMapEntry instances. 255ffd83dbSDimitry Andric class StringMapEntryBase { 265ffd83dbSDimitry Andric size_t keyLength; 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric public: 295ffd83dbSDimitry Andric explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {} 305ffd83dbSDimitry Andric 315ffd83dbSDimitry Andric size_t getKeyLength() const { return keyLength; } 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric protected: 34fe6060f1SDimitry Andric /// Helper to tail-allocate \p Key. It'd be nice to generalize this so it 35fe6060f1SDimitry Andric /// could be reused elsewhere, maybe even taking an llvm::function_ref to 36fe6060f1SDimitry Andric /// type-erase the allocator and put it in a source file. 37fe6060f1SDimitry Andric template <typename AllocatorTy> 38fe6060f1SDimitry Andric static void *allocateWithKey(size_t EntrySize, size_t EntryAlign, 39fe6060f1SDimitry Andric StringRef Key, AllocatorTy &Allocator); 405ffd83dbSDimitry Andric }; 415ffd83dbSDimitry Andric 42fe6060f1SDimitry Andric // Define out-of-line to dissuade inlining. 43fe6060f1SDimitry Andric template <typename AllocatorTy> 44fe6060f1SDimitry Andric void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign, 45fe6060f1SDimitry Andric StringRef Key, 46fe6060f1SDimitry Andric AllocatorTy &Allocator) { 47fe6060f1SDimitry Andric size_t KeyLength = Key.size(); 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric // Allocate a new item with space for the string at the end and a null 50fe6060f1SDimitry Andric // terminator. 51fe6060f1SDimitry Andric size_t AllocSize = EntrySize + KeyLength + 1; 52fe6060f1SDimitry Andric void *Allocation = Allocator.Allocate(AllocSize, EntryAlign); 53fe6060f1SDimitry Andric assert(Allocation && "Unhandled out-of-memory"); 54fe6060f1SDimitry Andric 55fe6060f1SDimitry Andric // Copy the string information. 56fe6060f1SDimitry Andric char *Buffer = reinterpret_cast<char *>(Allocation) + EntrySize; 57fe6060f1SDimitry Andric if (KeyLength > 0) 58fe6060f1SDimitry Andric ::memcpy(Buffer, Key.data(), KeyLength); 59fe6060f1SDimitry Andric Buffer[KeyLength] = 0; // Null terminate for convenience of clients. 60fe6060f1SDimitry Andric return Allocation; 61fe6060f1SDimitry Andric } 62fe6060f1SDimitry Andric 635ffd83dbSDimitry Andric /// StringMapEntryStorage - Holds the value in a StringMapEntry. 645ffd83dbSDimitry Andric /// 655ffd83dbSDimitry Andric /// Factored out into a separate base class to make it easier to specialize. 665ffd83dbSDimitry Andric /// This is primarily intended to support StringSet, which doesn't need a value 675ffd83dbSDimitry Andric /// stored at all. 685ffd83dbSDimitry Andric template <typename ValueTy> 695ffd83dbSDimitry Andric class StringMapEntryStorage : public StringMapEntryBase { 705ffd83dbSDimitry Andric public: 715ffd83dbSDimitry Andric ValueTy second; 725ffd83dbSDimitry Andric 735ffd83dbSDimitry Andric explicit StringMapEntryStorage(size_t keyLength) 745ffd83dbSDimitry Andric : StringMapEntryBase(keyLength), second() {} 755ffd83dbSDimitry Andric template <typename... InitTy> 765ffd83dbSDimitry Andric StringMapEntryStorage(size_t keyLength, InitTy &&... initVals) 775ffd83dbSDimitry Andric : StringMapEntryBase(keyLength), 785ffd83dbSDimitry Andric second(std::forward<InitTy>(initVals)...) {} 795ffd83dbSDimitry Andric StringMapEntryStorage(StringMapEntryStorage &e) = delete; 805ffd83dbSDimitry Andric 815ffd83dbSDimitry Andric const ValueTy &getValue() const { return second; } 825ffd83dbSDimitry Andric ValueTy &getValue() { return second; } 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric void setValue(const ValueTy &V) { second = V; } 855ffd83dbSDimitry Andric }; 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase { 885ffd83dbSDimitry Andric public: 89fe6060f1SDimitry Andric explicit StringMapEntryStorage(size_t keyLength, NoneType = None) 905ffd83dbSDimitry Andric : StringMapEntryBase(keyLength) {} 915ffd83dbSDimitry Andric StringMapEntryStorage(StringMapEntryStorage &entry) = delete; 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric NoneType getValue() const { return None; } 945ffd83dbSDimitry Andric }; 955ffd83dbSDimitry Andric 965ffd83dbSDimitry Andric /// StringMapEntry - This is used to represent one value that is inserted into 975ffd83dbSDimitry Andric /// a StringMap. It contains the Value itself and the key: the string length 985ffd83dbSDimitry Andric /// and data. 995ffd83dbSDimitry Andric template <typename ValueTy> 1005ffd83dbSDimitry Andric class StringMapEntry final : public StringMapEntryStorage<ValueTy> { 1015ffd83dbSDimitry Andric public: 1025ffd83dbSDimitry Andric using StringMapEntryStorage<ValueTy>::StringMapEntryStorage; 1035ffd83dbSDimitry Andric 1045ffd83dbSDimitry Andric StringRef getKey() const { 1055ffd83dbSDimitry Andric return StringRef(getKeyData(), this->getKeyLength()); 1065ffd83dbSDimitry Andric } 1075ffd83dbSDimitry Andric 1085ffd83dbSDimitry Andric /// getKeyData - Return the start of the string data that is the key for this 1095ffd83dbSDimitry Andric /// value. The string data is always stored immediately after the 1105ffd83dbSDimitry Andric /// StringMapEntry object. 1115ffd83dbSDimitry Andric const char *getKeyData() const { 1125ffd83dbSDimitry Andric return reinterpret_cast<const char *>(this + 1); 1135ffd83dbSDimitry Andric } 1145ffd83dbSDimitry Andric 1155ffd83dbSDimitry Andric StringRef first() const { 1165ffd83dbSDimitry Andric return StringRef(getKeyData(), this->getKeyLength()); 1175ffd83dbSDimitry Andric } 1185ffd83dbSDimitry Andric 1195ffd83dbSDimitry Andric /// Create a StringMapEntry for the specified key construct the value using 1205ffd83dbSDimitry Andric /// \p InitiVals. 1215ffd83dbSDimitry Andric template <typename AllocatorTy, typename... InitTy> 1225ffd83dbSDimitry Andric static StringMapEntry *Create(StringRef key, AllocatorTy &allocator, 1235ffd83dbSDimitry Andric InitTy &&... initVals) { 124fe6060f1SDimitry Andric return new (StringMapEntryBase::allocateWithKey( 125fe6060f1SDimitry Andric sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator)) 126fe6060f1SDimitry Andric StringMapEntry(key.size(), std::forward<InitTy>(initVals)...); 1275ffd83dbSDimitry Andric } 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 1305ffd83dbSDimitry Andric /// into a StringMapEntry, return the StringMapEntry itself. 1315ffd83dbSDimitry Andric static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) { 1325ffd83dbSDimitry Andric char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>); 1335ffd83dbSDimitry Andric return *reinterpret_cast<StringMapEntry *>(ptr); 1345ffd83dbSDimitry Andric } 1355ffd83dbSDimitry Andric 1365ffd83dbSDimitry Andric /// Destroy - Destroy this StringMapEntry, releasing memory back to the 1375ffd83dbSDimitry Andric /// specified allocator. 1385ffd83dbSDimitry Andric template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) { 1395ffd83dbSDimitry Andric // Free memory referenced by the item. 1405ffd83dbSDimitry Andric size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1; 1415ffd83dbSDimitry Andric this->~StringMapEntry(); 1425ffd83dbSDimitry Andric allocator.Deallocate(static_cast<void *>(this), AllocSize, 1435ffd83dbSDimitry Andric alignof(StringMapEntry)); 1445ffd83dbSDimitry Andric } 1455ffd83dbSDimitry Andric }; 1465ffd83dbSDimitry Andric 1475ffd83dbSDimitry Andric } // end namespace llvm 1485ffd83dbSDimitry Andric 1495ffd83dbSDimitry Andric #endif // LLVM_ADT_STRINGMAPENTRY_H 150