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 185ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h" 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric namespace llvm { 215ffd83dbSDimitry Andric 225ffd83dbSDimitry Andric /// StringMapEntryBase - Shared base class of StringMapEntry instances. 235ffd83dbSDimitry Andric class StringMapEntryBase { 245ffd83dbSDimitry Andric size_t keyLength; 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric public: 275ffd83dbSDimitry Andric explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {} 285ffd83dbSDimitry Andric 295ffd83dbSDimitry Andric size_t getKeyLength() const { return keyLength; } 30*fe6060f1SDimitry Andric 31*fe6060f1SDimitry Andric protected: 32*fe6060f1SDimitry Andric /// Helper to tail-allocate \p Key. It'd be nice to generalize this so it 33*fe6060f1SDimitry Andric /// could be reused elsewhere, maybe even taking an llvm::function_ref to 34*fe6060f1SDimitry Andric /// type-erase the allocator and put it in a source file. 35*fe6060f1SDimitry Andric template <typename AllocatorTy> 36*fe6060f1SDimitry Andric static void *allocateWithKey(size_t EntrySize, size_t EntryAlign, 37*fe6060f1SDimitry Andric StringRef Key, AllocatorTy &Allocator); 385ffd83dbSDimitry Andric }; 395ffd83dbSDimitry Andric 40*fe6060f1SDimitry Andric // Define out-of-line to dissuade inlining. 41*fe6060f1SDimitry Andric template <typename AllocatorTy> 42*fe6060f1SDimitry Andric void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign, 43*fe6060f1SDimitry Andric StringRef Key, 44*fe6060f1SDimitry Andric AllocatorTy &Allocator) { 45*fe6060f1SDimitry Andric size_t KeyLength = Key.size(); 46*fe6060f1SDimitry Andric 47*fe6060f1SDimitry Andric // Allocate a new item with space for the string at the end and a null 48*fe6060f1SDimitry Andric // terminator. 49*fe6060f1SDimitry Andric size_t AllocSize = EntrySize + KeyLength + 1; 50*fe6060f1SDimitry Andric void *Allocation = Allocator.Allocate(AllocSize, EntryAlign); 51*fe6060f1SDimitry Andric assert(Allocation && "Unhandled out-of-memory"); 52*fe6060f1SDimitry Andric 53*fe6060f1SDimitry Andric // Copy the string information. 54*fe6060f1SDimitry Andric char *Buffer = reinterpret_cast<char *>(Allocation) + EntrySize; 55*fe6060f1SDimitry Andric if (KeyLength > 0) 56*fe6060f1SDimitry Andric ::memcpy(Buffer, Key.data(), KeyLength); 57*fe6060f1SDimitry Andric Buffer[KeyLength] = 0; // Null terminate for convenience of clients. 58*fe6060f1SDimitry Andric return Allocation; 59*fe6060f1SDimitry Andric } 60*fe6060f1SDimitry Andric 615ffd83dbSDimitry Andric /// StringMapEntryStorage - Holds the value in a StringMapEntry. 625ffd83dbSDimitry Andric /// 635ffd83dbSDimitry Andric /// Factored out into a separate base class to make it easier to specialize. 645ffd83dbSDimitry Andric /// This is primarily intended to support StringSet, which doesn't need a value 655ffd83dbSDimitry Andric /// stored at all. 665ffd83dbSDimitry Andric template <typename ValueTy> 675ffd83dbSDimitry Andric class StringMapEntryStorage : public StringMapEntryBase { 685ffd83dbSDimitry Andric public: 695ffd83dbSDimitry Andric ValueTy second; 705ffd83dbSDimitry Andric 715ffd83dbSDimitry Andric explicit StringMapEntryStorage(size_t keyLength) 725ffd83dbSDimitry Andric : StringMapEntryBase(keyLength), second() {} 735ffd83dbSDimitry Andric template <typename... InitTy> 745ffd83dbSDimitry Andric StringMapEntryStorage(size_t keyLength, InitTy &&... initVals) 755ffd83dbSDimitry Andric : StringMapEntryBase(keyLength), 765ffd83dbSDimitry Andric second(std::forward<InitTy>(initVals)...) {} 775ffd83dbSDimitry Andric StringMapEntryStorage(StringMapEntryStorage &e) = delete; 785ffd83dbSDimitry Andric 795ffd83dbSDimitry Andric const ValueTy &getValue() const { return second; } 805ffd83dbSDimitry Andric ValueTy &getValue() { return second; } 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric void setValue(const ValueTy &V) { second = V; } 835ffd83dbSDimitry Andric }; 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase { 865ffd83dbSDimitry Andric public: 87*fe6060f1SDimitry Andric explicit StringMapEntryStorage(size_t keyLength, NoneType = None) 885ffd83dbSDimitry Andric : StringMapEntryBase(keyLength) {} 895ffd83dbSDimitry Andric StringMapEntryStorage(StringMapEntryStorage &entry) = delete; 905ffd83dbSDimitry Andric 915ffd83dbSDimitry Andric NoneType getValue() const { return None; } 925ffd83dbSDimitry Andric }; 935ffd83dbSDimitry Andric 945ffd83dbSDimitry Andric /// StringMapEntry - This is used to represent one value that is inserted into 955ffd83dbSDimitry Andric /// a StringMap. It contains the Value itself and the key: the string length 965ffd83dbSDimitry Andric /// and data. 975ffd83dbSDimitry Andric template <typename ValueTy> 985ffd83dbSDimitry Andric class StringMapEntry final : public StringMapEntryStorage<ValueTy> { 995ffd83dbSDimitry Andric public: 1005ffd83dbSDimitry Andric using StringMapEntryStorage<ValueTy>::StringMapEntryStorage; 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric StringRef getKey() const { 1035ffd83dbSDimitry Andric return StringRef(getKeyData(), this->getKeyLength()); 1045ffd83dbSDimitry Andric } 1055ffd83dbSDimitry Andric 1065ffd83dbSDimitry Andric /// getKeyData - Return the start of the string data that is the key for this 1075ffd83dbSDimitry Andric /// value. The string data is always stored immediately after the 1085ffd83dbSDimitry Andric /// StringMapEntry object. 1095ffd83dbSDimitry Andric const char *getKeyData() const { 1105ffd83dbSDimitry Andric return reinterpret_cast<const char *>(this + 1); 1115ffd83dbSDimitry Andric } 1125ffd83dbSDimitry Andric 1135ffd83dbSDimitry Andric StringRef first() const { 1145ffd83dbSDimitry Andric return StringRef(getKeyData(), this->getKeyLength()); 1155ffd83dbSDimitry Andric } 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric /// Create a StringMapEntry for the specified key construct the value using 1185ffd83dbSDimitry Andric /// \p InitiVals. 1195ffd83dbSDimitry Andric template <typename AllocatorTy, typename... InitTy> 1205ffd83dbSDimitry Andric static StringMapEntry *Create(StringRef key, AllocatorTy &allocator, 1215ffd83dbSDimitry Andric InitTy &&... initVals) { 122*fe6060f1SDimitry Andric return new (StringMapEntryBase::allocateWithKey( 123*fe6060f1SDimitry Andric sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator)) 124*fe6060f1SDimitry Andric StringMapEntry(key.size(), std::forward<InitTy>(initVals)...); 1255ffd83dbSDimitry Andric } 1265ffd83dbSDimitry Andric 1275ffd83dbSDimitry Andric /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 1285ffd83dbSDimitry Andric /// into a StringMapEntry, return the StringMapEntry itself. 1295ffd83dbSDimitry Andric static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) { 1305ffd83dbSDimitry Andric char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>); 1315ffd83dbSDimitry Andric return *reinterpret_cast<StringMapEntry *>(ptr); 1325ffd83dbSDimitry Andric } 1335ffd83dbSDimitry Andric 1345ffd83dbSDimitry Andric /// Destroy - Destroy this StringMapEntry, releasing memory back to the 1355ffd83dbSDimitry Andric /// specified allocator. 1365ffd83dbSDimitry Andric template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) { 1375ffd83dbSDimitry Andric // Free memory referenced by the item. 1385ffd83dbSDimitry Andric size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1; 1395ffd83dbSDimitry Andric this->~StringMapEntry(); 1405ffd83dbSDimitry Andric allocator.Deallocate(static_cast<void *>(this), AllocSize, 1415ffd83dbSDimitry Andric alignof(StringMapEntry)); 1425ffd83dbSDimitry Andric } 1435ffd83dbSDimitry Andric }; 1445ffd83dbSDimitry Andric 1455ffd83dbSDimitry Andric } // end namespace llvm 1465ffd83dbSDimitry Andric 1475ffd83dbSDimitry Andric #endif // LLVM_ADT_STRINGMAPENTRY_H 148