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 
32 /// StringMapEntryStorage - Holds the value in a StringMapEntry.
33 ///
34 /// Factored out into a separate base class to make it easier to specialize.
35 /// This is primarily intended to support StringSet, which doesn't need a value
36 /// stored at all.
37 template <typename ValueTy>
38 class StringMapEntryStorage : public StringMapEntryBase {
39 public:
40   ValueTy second;
41 
42   explicit StringMapEntryStorage(size_t keyLength)
43       : StringMapEntryBase(keyLength), second() {}
44   template <typename... InitTy>
45   StringMapEntryStorage(size_t keyLength, InitTy &&... initVals)
46       : StringMapEntryBase(keyLength),
47         second(std::forward<InitTy>(initVals)...) {}
48   StringMapEntryStorage(StringMapEntryStorage &e) = delete;
49 
50   const ValueTy &getValue() const { return second; }
51   ValueTy &getValue() { return second; }
52 
53   void setValue(const ValueTy &V) { second = V; }
54 };
55 
56 template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase {
57 public:
58   explicit StringMapEntryStorage(size_t keyLength, NoneType none = None)
59       : StringMapEntryBase(keyLength) {}
60   StringMapEntryStorage(StringMapEntryStorage &entry) = delete;
61 
62   NoneType getValue() const { return None; }
63 };
64 
65 /// StringMapEntry - This is used to represent one value that is inserted into
66 /// a StringMap.  It contains the Value itself and the key: the string length
67 /// and data.
68 template <typename ValueTy>
69 class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
70 public:
71   using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
72 
73   StringRef getKey() const {
74     return StringRef(getKeyData(), this->getKeyLength());
75   }
76 
77   /// getKeyData - Return the start of the string data that is the key for this
78   /// value.  The string data is always stored immediately after the
79   /// StringMapEntry object.
80   const char *getKeyData() const {
81     return reinterpret_cast<const char *>(this + 1);
82   }
83 
84   StringRef first() const {
85     return StringRef(getKeyData(), this->getKeyLength());
86   }
87 
88   /// Create a StringMapEntry for the specified key construct the value using
89   /// \p InitiVals.
90   template <typename AllocatorTy, typename... InitTy>
91   static StringMapEntry *Create(StringRef key, AllocatorTy &allocator,
92                                 InitTy &&... initVals) {
93     size_t keyLength = key.size();
94 
95     // Allocate a new item with space for the string at the end and a null
96     // terminator.
97     size_t allocSize = sizeof(StringMapEntry) + keyLength + 1;
98     size_t alignment = alignof(StringMapEntry);
99 
100     StringMapEntry *newItem =
101         static_cast<StringMapEntry *>(allocator.Allocate(allocSize, alignment));
102     assert(newItem && "Unhandled out-of-memory");
103 
104     // Construct the value.
105     new (newItem) StringMapEntry(keyLength, std::forward<InitTy>(initVals)...);
106 
107     // Copy the string information.
108     char *strBuffer = const_cast<char *>(newItem->getKeyData());
109     if (keyLength > 0)
110       memcpy(strBuffer, key.data(), keyLength);
111     strBuffer[keyLength] = 0; // Null terminate for convenience of clients.
112     return newItem;
113   }
114 
115   /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
116   /// into a StringMapEntry, return the StringMapEntry itself.
117   static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) {
118     char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>);
119     return *reinterpret_cast<StringMapEntry *>(ptr);
120   }
121 
122   /// Destroy - Destroy this StringMapEntry, releasing memory back to the
123   /// specified allocator.
124   template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) {
125     // Free memory referenced by the item.
126     size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1;
127     this->~StringMapEntry();
128     allocator.Deallocate(static_cast<void *>(this), AllocSize,
129                          alignof(StringMapEntry));
130   }
131 };
132 
133 } // end namespace llvm
134 
135 #endif // LLVM_ADT_STRINGMAPENTRY_H
136