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