StringMapEntry.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- StringMapEntry.h - String Hash table map interface -------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// This file defines the StringMapEntry class - it is intended to be a low
  16. /// dependency implementation detail of StringMap that is more suitable for
  17. /// inclusion in public headers than StringMap.h itself is.
  18. ///
  19. //===----------------------------------------------------------------------===//
  20. #ifndef LLVM_ADT_STRINGMAPENTRY_H
  21. #define LLVM_ADT_STRINGMAPENTRY_H
  22. #include "llvm/ADT/StringRef.h"
  23. #include <optional>
  24. namespace llvm {
  25. /// StringMapEntryBase - Shared base class of StringMapEntry instances.
  26. class StringMapEntryBase {
  27. size_t keyLength;
  28. public:
  29. explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {}
  30. size_t getKeyLength() const { return keyLength; }
  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. // Define out-of-line to dissuade inlining.
  40. template <typename AllocatorTy>
  41. void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign,
  42. StringRef Key,
  43. AllocatorTy &Allocator) {
  44. size_t KeyLength = Key.size();
  45. // Allocate a new item with space for the string at the end and a null
  46. // terminator.
  47. size_t AllocSize = EntrySize + KeyLength + 1;
  48. void *Allocation = Allocator.Allocate(AllocSize, EntryAlign);
  49. assert(Allocation && "Unhandled out-of-memory");
  50. // Copy the string information.
  51. char *Buffer = reinterpret_cast<char *>(Allocation) + EntrySize;
  52. if (KeyLength > 0)
  53. ::memcpy(Buffer, Key.data(), KeyLength);
  54. Buffer[KeyLength] = 0; // Null terminate for convenience of clients.
  55. return Allocation;
  56. }
  57. /// StringMapEntryStorage - Holds the value in a StringMapEntry.
  58. ///
  59. /// Factored out into a separate base class to make it easier to specialize.
  60. /// This is primarily intended to support StringSet, which doesn't need a value
  61. /// stored at all.
  62. template <typename ValueTy>
  63. class StringMapEntryStorage : public StringMapEntryBase {
  64. public:
  65. ValueTy second;
  66. explicit StringMapEntryStorage(size_t keyLength)
  67. : StringMapEntryBase(keyLength), second() {}
  68. template <typename... InitTy>
  69. StringMapEntryStorage(size_t keyLength, InitTy &&...initVals)
  70. : StringMapEntryBase(keyLength),
  71. second(std::forward<InitTy>(initVals)...) {}
  72. StringMapEntryStorage(StringMapEntryStorage &e) = delete;
  73. const ValueTy &getValue() const { return second; }
  74. ValueTy &getValue() { return second; }
  75. void setValue(const ValueTy &V) { second = V; }
  76. };
  77. template <>
  78. class StringMapEntryStorage<std::nullopt_t> : public StringMapEntryBase {
  79. public:
  80. explicit StringMapEntryStorage(size_t keyLength,
  81. std::nullopt_t = std::nullopt)
  82. : StringMapEntryBase(keyLength) {}
  83. StringMapEntryStorage(StringMapEntryStorage &entry) = delete;
  84. std::nullopt_t getValue() const { return std::nullopt; }
  85. };
  86. /// StringMapEntry - This is used to represent one value that is inserted into
  87. /// a StringMap. It contains the Value itself and the key: the string length
  88. /// and data.
  89. template <typename ValueTy>
  90. class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
  91. public:
  92. using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
  93. using ValueType = ValueTy;
  94. StringRef getKey() const {
  95. return StringRef(getKeyData(), this->getKeyLength());
  96. }
  97. /// getKeyData - Return the start of the string data that is the key for this
  98. /// value. The string data is always stored immediately after the
  99. /// StringMapEntry object.
  100. const char *getKeyData() const {
  101. return reinterpret_cast<const char *>(this + 1);
  102. }
  103. StringRef first() const {
  104. return StringRef(getKeyData(), this->getKeyLength());
  105. }
  106. /// Create a StringMapEntry for the specified key construct the value using
  107. /// \p InitiVals.
  108. template <typename AllocatorTy, typename... InitTy>
  109. static StringMapEntry *create(StringRef key, AllocatorTy &allocator,
  110. InitTy &&...initVals) {
  111. return new (StringMapEntryBase::allocateWithKey(
  112. sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator))
  113. StringMapEntry(key.size(), std::forward<InitTy>(initVals)...);
  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. /// Destroy - Destroy this StringMapEntry, releasing memory back to the
  122. /// specified allocator.
  123. template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) {
  124. // Free memory referenced by the item.
  125. size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1;
  126. this->~StringMapEntry();
  127. allocator.Deallocate(static_cast<void *>(this), AllocSize,
  128. alignof(StringMapEntry));
  129. }
  130. };
  131. // Allow structured bindings on StringMapEntry.
  132. template <std::size_t Index, typename ValueTy>
  133. decltype(auto) get(const StringMapEntry<ValueTy> &E) {
  134. static_assert(Index < 2);
  135. if constexpr (Index == 0)
  136. return E.first();
  137. else
  138. return E.second;
  139. }
  140. } // end namespace llvm
  141. namespace std {
  142. template <typename ValueTy>
  143. struct tuple_size<llvm::StringMapEntry<ValueTy>>
  144. : std::integral_constant<std::size_t, 2> {};
  145. template <std::size_t I, typename ValueTy>
  146. struct tuple_element<I, llvm::StringMapEntry<ValueTy>>
  147. : std::conditional<I == 0, llvm::StringRef, ValueTy> {};
  148. } // namespace std
  149. #endif // LLVM_ADT_STRINGMAPENTRY_H
  150. #ifdef __GNUC__
  151. #pragma GCC diagnostic pop
  152. #endif