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
20namespace llvm {
21
22/// StringMapEntryBase - Shared base class of StringMapEntry instances.
23class StringMapEntryBase {
24  size_t keyLength;
25
26public:
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.
37template <typename ValueTy>
38class StringMapEntryStorage : public StringMapEntryBase {
39public:
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
56template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase {
57public:
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.
68template <typename ValueTy>
69class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
70public:
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