xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/ADT/StringMapEntry.h (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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