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