1*5ffd83dbSDimitry Andric //===- StringMapEntry.h - String Hash table map interface -------*- C++ -*-===// 2*5ffd83dbSDimitry Andric // 3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5ffd83dbSDimitry Andric // 7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 8*5ffd83dbSDimitry Andric // 9*5ffd83dbSDimitry Andric // This file defines the StringMapEntry class - it is intended to be a low 10*5ffd83dbSDimitry Andric // dependency implementation detail of StringMap that is more suitable for 11*5ffd83dbSDimitry Andric // inclusion in public headers than StringMap.h itself is. 12*5ffd83dbSDimitry Andric // 13*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 14*5ffd83dbSDimitry Andric 15*5ffd83dbSDimitry Andric #ifndef LLVM_ADT_STRINGMAPENTRY_H 16*5ffd83dbSDimitry Andric #define LLVM_ADT_STRINGMAPENTRY_H 17*5ffd83dbSDimitry Andric 18*5ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h" 19*5ffd83dbSDimitry Andric 20*5ffd83dbSDimitry Andric namespace llvm { 21*5ffd83dbSDimitry Andric 22*5ffd83dbSDimitry Andric /// StringMapEntryBase - Shared base class of StringMapEntry instances. 23*5ffd83dbSDimitry Andric class StringMapEntryBase { 24*5ffd83dbSDimitry Andric size_t keyLength; 25*5ffd83dbSDimitry Andric 26*5ffd83dbSDimitry Andric public: 27*5ffd83dbSDimitry Andric explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {} 28*5ffd83dbSDimitry Andric 29*5ffd83dbSDimitry Andric size_t getKeyLength() const { return keyLength; } 30*5ffd83dbSDimitry Andric }; 31*5ffd83dbSDimitry Andric 32*5ffd83dbSDimitry Andric /// StringMapEntryStorage - Holds the value in a StringMapEntry. 33*5ffd83dbSDimitry Andric /// 34*5ffd83dbSDimitry Andric /// Factored out into a separate base class to make it easier to specialize. 35*5ffd83dbSDimitry Andric /// This is primarily intended to support StringSet, which doesn't need a value 36*5ffd83dbSDimitry Andric /// stored at all. 37*5ffd83dbSDimitry Andric template <typename ValueTy> 38*5ffd83dbSDimitry Andric class StringMapEntryStorage : public StringMapEntryBase { 39*5ffd83dbSDimitry Andric public: 40*5ffd83dbSDimitry Andric ValueTy second; 41*5ffd83dbSDimitry Andric 42*5ffd83dbSDimitry Andric explicit StringMapEntryStorage(size_t keyLength) 43*5ffd83dbSDimitry Andric : StringMapEntryBase(keyLength), second() {} 44*5ffd83dbSDimitry Andric template <typename... InitTy> 45*5ffd83dbSDimitry Andric StringMapEntryStorage(size_t keyLength, InitTy &&... initVals) 46*5ffd83dbSDimitry Andric : StringMapEntryBase(keyLength), 47*5ffd83dbSDimitry Andric second(std::forward<InitTy>(initVals)...) {} 48*5ffd83dbSDimitry Andric StringMapEntryStorage(StringMapEntryStorage &e) = delete; 49*5ffd83dbSDimitry Andric 50*5ffd83dbSDimitry Andric const ValueTy &getValue() const { return second; } 51*5ffd83dbSDimitry Andric ValueTy &getValue() { return second; } 52*5ffd83dbSDimitry Andric 53*5ffd83dbSDimitry Andric void setValue(const ValueTy &V) { second = V; } 54*5ffd83dbSDimitry Andric }; 55*5ffd83dbSDimitry Andric 56*5ffd83dbSDimitry Andric template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase { 57*5ffd83dbSDimitry Andric public: 58*5ffd83dbSDimitry Andric explicit StringMapEntryStorage(size_t keyLength, NoneType none = None) 59*5ffd83dbSDimitry Andric : StringMapEntryBase(keyLength) {} 60*5ffd83dbSDimitry Andric StringMapEntryStorage(StringMapEntryStorage &entry) = delete; 61*5ffd83dbSDimitry Andric 62*5ffd83dbSDimitry Andric NoneType getValue() const { return None; } 63*5ffd83dbSDimitry Andric }; 64*5ffd83dbSDimitry Andric 65*5ffd83dbSDimitry Andric /// StringMapEntry - This is used to represent one value that is inserted into 66*5ffd83dbSDimitry Andric /// a StringMap. It contains the Value itself and the key: the string length 67*5ffd83dbSDimitry Andric /// and data. 68*5ffd83dbSDimitry Andric template <typename ValueTy> 69*5ffd83dbSDimitry Andric class StringMapEntry final : public StringMapEntryStorage<ValueTy> { 70*5ffd83dbSDimitry Andric public: 71*5ffd83dbSDimitry Andric using StringMapEntryStorage<ValueTy>::StringMapEntryStorage; 72*5ffd83dbSDimitry Andric 73*5ffd83dbSDimitry Andric StringRef getKey() const { 74*5ffd83dbSDimitry Andric return StringRef(getKeyData(), this->getKeyLength()); 75*5ffd83dbSDimitry Andric } 76*5ffd83dbSDimitry Andric 77*5ffd83dbSDimitry Andric /// getKeyData - Return the start of the string data that is the key for this 78*5ffd83dbSDimitry Andric /// value. The string data is always stored immediately after the 79*5ffd83dbSDimitry Andric /// StringMapEntry object. 80*5ffd83dbSDimitry Andric const char *getKeyData() const { 81*5ffd83dbSDimitry Andric return reinterpret_cast<const char *>(this + 1); 82*5ffd83dbSDimitry Andric } 83*5ffd83dbSDimitry Andric 84*5ffd83dbSDimitry Andric StringRef first() const { 85*5ffd83dbSDimitry Andric return StringRef(getKeyData(), this->getKeyLength()); 86*5ffd83dbSDimitry Andric } 87*5ffd83dbSDimitry Andric 88*5ffd83dbSDimitry Andric /// Create a StringMapEntry for the specified key construct the value using 89*5ffd83dbSDimitry Andric /// \p InitiVals. 90*5ffd83dbSDimitry Andric template <typename AllocatorTy, typename... InitTy> 91*5ffd83dbSDimitry Andric static StringMapEntry *Create(StringRef key, AllocatorTy &allocator, 92*5ffd83dbSDimitry Andric InitTy &&... initVals) { 93*5ffd83dbSDimitry Andric size_t keyLength = key.size(); 94*5ffd83dbSDimitry Andric 95*5ffd83dbSDimitry Andric // Allocate a new item with space for the string at the end and a null 96*5ffd83dbSDimitry Andric // terminator. 97*5ffd83dbSDimitry Andric size_t allocSize = sizeof(StringMapEntry) + keyLength + 1; 98*5ffd83dbSDimitry Andric size_t alignment = alignof(StringMapEntry); 99*5ffd83dbSDimitry Andric 100*5ffd83dbSDimitry Andric StringMapEntry *newItem = 101*5ffd83dbSDimitry Andric static_cast<StringMapEntry *>(allocator.Allocate(allocSize, alignment)); 102*5ffd83dbSDimitry Andric assert(newItem && "Unhandled out-of-memory"); 103*5ffd83dbSDimitry Andric 104*5ffd83dbSDimitry Andric // Construct the value. 105*5ffd83dbSDimitry Andric new (newItem) StringMapEntry(keyLength, std::forward<InitTy>(initVals)...); 106*5ffd83dbSDimitry Andric 107*5ffd83dbSDimitry Andric // Copy the string information. 108*5ffd83dbSDimitry Andric char *strBuffer = const_cast<char *>(newItem->getKeyData()); 109*5ffd83dbSDimitry Andric if (keyLength > 0) 110*5ffd83dbSDimitry Andric memcpy(strBuffer, key.data(), keyLength); 111*5ffd83dbSDimitry Andric strBuffer[keyLength] = 0; // Null terminate for convenience of clients. 112*5ffd83dbSDimitry Andric return newItem; 113*5ffd83dbSDimitry Andric } 114*5ffd83dbSDimitry Andric 115*5ffd83dbSDimitry Andric /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 116*5ffd83dbSDimitry Andric /// into a StringMapEntry, return the StringMapEntry itself. 117*5ffd83dbSDimitry Andric static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) { 118*5ffd83dbSDimitry Andric char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>); 119*5ffd83dbSDimitry Andric return *reinterpret_cast<StringMapEntry *>(ptr); 120*5ffd83dbSDimitry Andric } 121*5ffd83dbSDimitry Andric 122*5ffd83dbSDimitry Andric /// Destroy - Destroy this StringMapEntry, releasing memory back to the 123*5ffd83dbSDimitry Andric /// specified allocator. 124*5ffd83dbSDimitry Andric template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) { 125*5ffd83dbSDimitry Andric // Free memory referenced by the item. 126*5ffd83dbSDimitry Andric size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1; 127*5ffd83dbSDimitry Andric this->~StringMapEntry(); 128*5ffd83dbSDimitry Andric allocator.Deallocate(static_cast<void *>(this), AllocSize, 129*5ffd83dbSDimitry Andric alignof(StringMapEntry)); 130*5ffd83dbSDimitry Andric } 131*5ffd83dbSDimitry Andric }; 132*5ffd83dbSDimitry Andric 133*5ffd83dbSDimitry Andric } // end namespace llvm 134*5ffd83dbSDimitry Andric 135*5ffd83dbSDimitry Andric #endif // LLVM_ADT_STRINGMAPENTRY_H 136