- //===- StringMapEntry.h - String Hash table map interface -------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- /// 
- /// \file 
- /// This file defines the StringMapEntry class - it is intended to be a low 
- /// dependency implementation detail of StringMap that is more suitable for 
- /// inclusion in public headers than StringMap.h itself is. 
- /// 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_ADT_STRINGMAPENTRY_H 
- #define LLVM_ADT_STRINGMAPENTRY_H 
-   
- #include "llvm/ADT/StringRef.h" 
- #include <optional> 
-   
- namespace llvm { 
-   
- /// StringMapEntryBase - Shared base class of StringMapEntry instances. 
- class StringMapEntryBase { 
-   size_t keyLength; 
-   
- public: 
-   explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {} 
-   
-   size_t getKeyLength() const { return keyLength; } 
-   
- protected: 
-   /// Helper to tail-allocate \p Key. It'd be nice to generalize this so it 
-   /// could be reused elsewhere, maybe even taking an llvm::function_ref to 
-   /// type-erase the allocator and put it in a source file. 
-   template <typename AllocatorTy> 
-   static void *allocateWithKey(size_t EntrySize, size_t EntryAlign, 
-                                StringRef Key, AllocatorTy &Allocator); 
- }; 
-   
- // Define out-of-line to dissuade inlining. 
- template <typename AllocatorTy> 
- void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign, 
-                                           StringRef Key, 
-                                           AllocatorTy &Allocator) { 
-   size_t KeyLength = Key.size(); 
-   
-   // Allocate a new item with space for the string at the end and a null 
-   // terminator. 
-   size_t AllocSize = EntrySize + KeyLength + 1; 
-   void *Allocation = Allocator.Allocate(AllocSize, EntryAlign); 
-   assert(Allocation && "Unhandled out-of-memory"); 
-   
-   // Copy the string information. 
-   char *Buffer = reinterpret_cast<char *>(Allocation) + EntrySize; 
-   if (KeyLength > 0) 
-     ::memcpy(Buffer, Key.data(), KeyLength); 
-   Buffer[KeyLength] = 0; // Null terminate for convenience of clients. 
-   return Allocation; 
- } 
-   
- /// StringMapEntryStorage - Holds the value in a StringMapEntry. 
- /// 
- /// Factored out into a separate base class to make it easier to specialize. 
- /// This is primarily intended to support StringSet, which doesn't need a value 
- /// stored at all. 
- template <typename ValueTy> 
- class StringMapEntryStorage : public StringMapEntryBase { 
- public: 
-   ValueTy second; 
-   
-   explicit StringMapEntryStorage(size_t keyLength) 
-       : StringMapEntryBase(keyLength), second() {} 
-   template <typename... InitTy> 
-   StringMapEntryStorage(size_t keyLength, InitTy &&...initVals) 
-       : StringMapEntryBase(keyLength), 
-         second(std::forward<InitTy>(initVals)...) {} 
-   StringMapEntryStorage(StringMapEntryStorage &e) = delete; 
-   
-   const ValueTy &getValue() const { return second; } 
-   ValueTy &getValue() { return second; } 
-   
-   void setValue(const ValueTy &V) { second = V; } 
- }; 
-   
- template <> 
- class StringMapEntryStorage<std::nullopt_t> : public StringMapEntryBase { 
- public: 
-   explicit StringMapEntryStorage(size_t keyLength, 
-                                  std::nullopt_t = std::nullopt) 
-       : StringMapEntryBase(keyLength) {} 
-   StringMapEntryStorage(StringMapEntryStorage &entry) = delete; 
-   
-   std::nullopt_t getValue() const { return std::nullopt; } 
- }; 
-   
- /// StringMapEntry - This is used to represent one value that is inserted into 
- /// a StringMap.  It contains the Value itself and the key: the string length 
- /// and data. 
- template <typename ValueTy> 
- class StringMapEntry final : public StringMapEntryStorage<ValueTy> { 
- public: 
-   using StringMapEntryStorage<ValueTy>::StringMapEntryStorage; 
-   
-   using ValueType = ValueTy; 
-   
-   StringRef getKey() const { 
-     return StringRef(getKeyData(), this->getKeyLength()); 
-   } 
-   
-   /// getKeyData - Return the start of the string data that is the key for this 
-   /// value.  The string data is always stored immediately after the 
-   /// StringMapEntry object. 
-   const char *getKeyData() const { 
-     return reinterpret_cast<const char *>(this + 1); 
-   } 
-   
-   StringRef first() const { 
-     return StringRef(getKeyData(), this->getKeyLength()); 
-   } 
-   
-   /// Create a StringMapEntry for the specified key construct the value using 
-   /// \p InitiVals. 
-   template <typename AllocatorTy, typename... InitTy> 
-   static StringMapEntry *create(StringRef key, AllocatorTy &allocator, 
-                                 InitTy &&...initVals) { 
-     return new (StringMapEntryBase::allocateWithKey( 
-         sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator)) 
-         StringMapEntry(key.size(), std::forward<InitTy>(initVals)...); 
-   } 
-   
-   /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 
-   /// into a StringMapEntry, return the StringMapEntry itself. 
-   static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) { 
-     char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>); 
-     return *reinterpret_cast<StringMapEntry *>(ptr); 
-   } 
-   
-   /// Destroy - Destroy this StringMapEntry, releasing memory back to the 
-   /// specified allocator. 
-   template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) { 
-     // Free memory referenced by the item. 
-     size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1; 
-     this->~StringMapEntry(); 
-     allocator.Deallocate(static_cast<void *>(this), AllocSize, 
-                          alignof(StringMapEntry)); 
-   } 
- }; 
-   
- // Allow structured bindings on StringMapEntry. 
- template <std::size_t Index, typename ValueTy> 
- decltype(auto) get(const StringMapEntry<ValueTy> &E) { 
-   static_assert(Index < 2); 
-   if constexpr (Index == 0) 
-     return E.first(); 
-   else 
-     return E.second; 
- } 
-   
- } // end namespace llvm 
-   
- namespace std { 
- template <typename ValueTy> 
- struct tuple_size<llvm::StringMapEntry<ValueTy>> 
-     : std::integral_constant<std::size_t, 2> {}; 
-   
- template <std::size_t I, typename ValueTy> 
- struct tuple_element<I, llvm::StringMapEntry<ValueTy>> 
-     : std::conditional<I == 0, llvm::StringRef, ValueTy> {}; 
- } // namespace std 
-   
- #endif // LLVM_ADT_STRINGMAPENTRY_H 
-