LLDB  mainline
FormattersContainer.h
Go to the documentation of this file.
1 //===-- FormattersContainer.h -----------------------------------*- 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 #ifndef LLDB_DATAFORMATTERS_FORMATTERSCONTAINER_H
10 #define LLDB_DATAFORMATTERS_FORMATTERSCONTAINER_H
11 
12 #include <functional>
13 #include <map>
14 #include <memory>
15 #include <mutex>
16 #include <string>
17 
18 #include "lldb/lldb-public.h"
19 
20 #include "lldb/Core/ValueObject.h"
28 
29 namespace lldb_private {
30 
32 public:
33  virtual ~IFormatChangeListener() = default;
34 
35  virtual void Changed() = 0;
36 
37  virtual uint32_t GetCurrentRevision() = 0;
38 };
39 
40 /// Class for matching type names.
41 class TypeMatcher {
44  /// False if m_type_name_regex should be used for matching. False if this is
45  /// just matching by comparing with m_type_name string.
46  bool m_is_regex;
47 
48  // if the user tries to add formatters for, say, "struct Foo" those will not
49  // match any type because of the way we strip qualifiers from typenames this
50  // method looks for the case where the user is adding a
51  // "class","struct","enum" or "union" Foo and strips the unnecessary qualifier
53  if (type.IsEmpty())
54  return type;
55 
56  std::string type_cstr(type.AsCString());
57  StringLexer type_lexer(type_cstr);
58 
59  type_lexer.AdvanceIf("class ");
60  type_lexer.AdvanceIf("enum ");
61  type_lexer.AdvanceIf("struct ");
62  type_lexer.AdvanceIf("union ");
63 
64  while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
65  ;
66 
67  return ConstString(type_lexer.GetUnlexed());
68  }
69 
70 public:
71  TypeMatcher() = delete;
72  /// Creates a matcher that accepts any type with exactly the given type name.
74  : m_type_name(type_name), m_is_regex(false) {}
75  /// Creates a matcher that accepts any type matching the given regex.
77  : m_type_name_regex(std::move(regex)), m_is_regex(true) {}
78 
79  /// True iff this matches the given type name.
80  bool Matches(ConstString type_name) const {
81  if (m_is_regex)
82  return m_type_name_regex.Execute(type_name.GetStringRef());
83  return m_type_name == type_name ||
85  }
86 
87  /// Returns the underlying match string for this TypeMatcher.
89  if (m_is_regex)
91  return StripTypeName(m_type_name);
92  }
93 
94  /// Returns true if this TypeMatcher and the given one were most created by
95  /// the same match string.
96  /// The main purpose of this function is to find existing TypeMatcher
97  /// instances by the user input that created them. This is necessary as LLDB
98  /// allows referencing existing TypeMatchers in commands by the user input
99  /// that originally created them:
100  /// (lldb) type summary add --summary-string \"A\" -x TypeName
101  /// (lldb) type summary delete TypeName
103  return GetMatchString() == other.GetMatchString();
104  }
105 };
106 
107 template <typename ValueType> class FormattersContainer {
108 public:
109  typedef typename std::shared_ptr<ValueType> ValueSP;
110  typedef std::vector<std::pair<TypeMatcher, ValueSP>> MapType;
111  typedef std::function<bool(const TypeMatcher &, const ValueSP &)>
113  typedef typename std::shared_ptr<FormattersContainer<ValueType>>
115 
116  friend class TypeCategoryImpl;
117 
119 
120  void Add(TypeMatcher matcher, const ValueSP &entry) {
121  if (listener)
122  entry->GetRevision() = listener->GetCurrentRevision();
123  else
124  entry->GetRevision() = 0;
125 
126  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
127  Delete(matcher);
128  m_map.emplace_back(std::move(matcher), std::move(entry));
129  if (listener)
130  listener->Changed();
131  }
132 
133  bool Delete(TypeMatcher matcher) {
134  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
135  for (auto iter = m_map.begin(); iter != m_map.end(); ++iter)
136  if (iter->first.CreatedBySameMatchString(matcher)) {
137  m_map.erase(iter);
138  if (listener)
139  listener->Changed();
140  return true;
141  }
142  return false;
143  }
144 
145  bool Get(ConstString type, ValueSP &entry) {
146  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
147  for (auto &formatter : llvm::reverse(m_map)) {
148  if (formatter.first.Matches(type)) {
149  entry = formatter.second;
150  return true;
151  }
152  }
153  return false;
154  }
155 
156  bool GetExact(TypeMatcher matcher, ValueSP &entry) {
157  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
158  for (const auto &pos : m_map)
159  if (pos.first.CreatedBySameMatchString(matcher)) {
160  entry = pos.second;
161  return true;
162  }
163  return false;
164  }
165 
166  ValueSP GetAtIndex(size_t index) {
167  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
168  if (index >= m_map.size())
169  return ValueSP();
170  return m_map[index].second;
171  }
172 
173  lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
174  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
175  if (index >= m_map.size())
176  return lldb::TypeNameSpecifierImplSP();
177  TypeMatcher type_matcher = m_map[index].first;
178  return std::make_shared<TypeNameSpecifierImpl>(
179  type_matcher.GetMatchString().GetStringRef(), true);
180  }
181 
182  void Clear() {
183  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
184  m_map.clear();
185  if (listener)
186  listener->Changed();
187  }
188 
189  void ForEach(ForEachCallback callback) {
190  if (callback) {
191  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
192  for (const auto &pos : m_map) {
193  const TypeMatcher &type = pos.first;
194  if (!callback(type, pos.second))
195  break;
196  }
197  }
198  }
199 
201  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
202  return m_map.size();
203  }
204 
206  ForEach([&request](const TypeMatcher &matcher, const ValueSP &value) {
208  return true;
209  });
210  }
211 
212 protected:
213  FormattersContainer(const FormattersContainer &) = delete;
214  const FormattersContainer &operator=(const FormattersContainer &) = delete;
215 
216  bool Get(const FormattersMatchVector &candidates, ValueSP &entry) {
217  for (const FormattersMatchCandidate &candidate : candidates) {
218  if (Get(candidate.GetTypeName(), entry)) {
219  if (candidate.IsMatch(entry) == false) {
220  entry.reset();
221  continue;
222  } else {
223  return true;
224  }
225  }
226  }
227  return false;
228  }
229 
231  std::recursive_mutex m_map_mutex;
233 };
234 
235 } // namespace lldb_private
236 
237 #endif // LLDB_DATAFORMATTERS_FORMATTERSCONTAINER_H
RegularExpression.h
lldb_private::TypeMatcher::StripTypeName
static ConstString StripTypeName(ConstString type)
Definition: FormattersContainer.h:52
lldb-public.h
lldb_private::FormattersContainer::ForEach
void ForEach(ForEachCallback callback)
Definition: FormattersContainer.h:189
lldb_private::RegularExpression
Definition: RegularExpression.h:18
lldb_private::TypeMatcher
Class for matching type names.
Definition: FormattersContainer.h:41
FormatClasses.h
lldb_private::FormattersContainer::Clear
void Clear()
Definition: FormattersContainer.h:182
lldb_private::CompletionRequest::TryCompleteCurrentArg
void TryCompleteCurrentArg(llvm::StringRef completion, llvm::StringRef description="")
Adds a possible completion string if the completion would complete the current argument.
Definition: CompletionRequest.h:180
lldb_private::FormattersContainer::GetAtIndex
ValueSP GetAtIndex(size_t index)
Definition: FormattersContainer.h:166
lldb_private::TypeMatcher::m_type_name_regex
RegularExpression m_type_name_regex
Definition: FormattersContainer.h:42
lldb_private::TypeMatcher::TypeMatcher
TypeMatcher(RegularExpression regex)
Creates a matcher that accepts any type matching the given regex.
Definition: FormattersContainer.h:76
lldb_private::ConstString::AsCString
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:193
lldb_private::FormattersContainer
Definition: FormattersContainer.h:107
lldb_private::FormattersContainer::Delete
bool Delete(TypeMatcher matcher)
Definition: FormattersContainer.h:133
lldb_private::FormattersContainer::FormattersContainer
FormattersContainer(IFormatChangeListener *lst)
Definition: FormattersContainer.h:118
lldb_private::TypeMatcher::TypeMatcher
TypeMatcher(ConstString type_name)
Creates a matcher that accepts any type with exactly the given type name.
Definition: FormattersContainer.h:73
lldb_private::StringLexer::GetUnlexed
std::string GetUnlexed()
Definition: StringLexer.cpp:73
lldb_private::IFormatChangeListener::Changed
virtual void Changed()=0
lldb_private::IFormatChangeListener::GetCurrentRevision
virtual uint32_t GetCurrentRevision()=0
lldb_private::ConstString::GetStringRef
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:202
lldb_private::ConstString::IsEmpty
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:304
lldb_private::FormattersMatchVector
std::vector< FormattersMatchCandidate > FormattersMatchVector
Definition: FormatClasses.h:81
lldb_private::FormattersContainer::m_map_mutex
std::recursive_mutex m_map_mutex
Definition: FormattersContainer.h:231
lldb_private::FormattersContainer::ValueSP
std::shared_ptr< ValueType > ValueSP
Definition: FormattersContainer.h:109
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::StringLexer::NextIf
bool NextIf(Character c)
Definition: StringLexer.cpp:21
lldb_private::FormattersMatchCandidate
Definition: FormatClasses.h:44
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:38
lldb_private::StringLexer::AdvanceIf
bool AdvanceIf(const std::string &token)
Definition: StringLexer.cpp:42
CompilerType.h
ValueObject.h
StringLexer.h
lldb_private::FormattersContainer::GetCount
uint32_t GetCount()
Definition: FormattersContainer.h:200
lldb_private::FormattersContainer::m_map
MapType m_map
Definition: FormattersContainer.h:230
lldb_private::FormattersContainer::operator=
const FormattersContainer & operator=(const FormattersContainer &)=delete
TypeSummary.h
lldb_private::FormattersContainer::Add
void Add(TypeMatcher matcher, const ValueSP &entry)
Definition: FormattersContainer.h:120
uint32_t
TypeSynthetic.h
lldb_private::TypeMatcher::m_type_name
ConstString m_type_name
Definition: FormattersContainer.h:43
lldb_private::FormattersContainer::AutoComplete
void AutoComplete(CompletionRequest &request)
Definition: FormattersContainer.h:205
lldb_private::FormattersContainer::ForEachCallback
std::function< bool(const TypeMatcher &, const ValueSP &)> ForEachCallback
Definition: FormattersContainer.h:112
TypeFormat.h
lldb_private::FormattersContainer::MapType
std::vector< std::pair< TypeMatcher, ValueSP > > MapType
Definition: FormattersContainer.h:110
lldb_private::FormattersContainer::SharedPointer
std::shared_ptr< FormattersContainer< ValueType > > SharedPointer
Definition: FormattersContainer.h:114
lldb_private::FormattersContainer::Get
bool Get(const FormattersMatchVector &candidates, ValueSP &entry)
Definition: FormattersContainer.h:216
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::IFormatChangeListener::~IFormatChangeListener
virtual ~IFormatChangeListener()=default
lldb_private::RegularExpression::Execute
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
Definition: RegularExpression.cpp:23
lldb_private::TypeMatcher::TypeMatcher
TypeMatcher()=delete
lldb_private::TypeCategoryImpl
Definition: TypeCategory.h:63
lldb_private::FormattersContainer::Get
bool Get(ConstString type, ValueSP &entry)
Definition: FormattersContainer.h:145
lldb_private::RegularExpression::GetText
llvm::StringRef GetText() const
Access the regular expression text.
Definition: RegularExpression.cpp:33
lldb_private::FormattersContainer::GetExact
bool GetExact(TypeMatcher matcher, ValueSP &entry)
Definition: FormattersContainer.h:156
lldb_private::FormattersContainer::GetTypeNameSpecifierAtIndex
lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index)
Definition: FormattersContainer.h:173
lldb_private::TypeMatcher::CreatedBySameMatchString
bool CreatedBySameMatchString(TypeMatcher other) const
Returns true if this TypeMatcher and the given one were most created by the same match string.
Definition: FormattersContainer.h:102
lldb_private::FormattersContainer::listener
IFormatChangeListener * listener
Definition: FormattersContainer.h:232
lldb_private::TypeMatcher::GetMatchString
ConstString GetMatchString() const
Returns the underlying match string for this TypeMatcher.
Definition: FormattersContainer.h:88
lldb_private::TypeMatcher::m_is_regex
bool m_is_regex
False if m_type_name_regex should be used for matching.
Definition: FormattersContainer.h:46
lldb_private::IFormatChangeListener
Definition: FormattersContainer.h:31
lldb_private::TypeMatcher::Matches
bool Matches(ConstString type_name) const
True iff this matches the given type name.
Definition: FormattersContainer.h:80
lldb_private::StringLexer
Definition: StringLexer.h:18
lldb_private::CompletionRequest
Definition: CompletionRequest.h:100