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 // if the user tries to add formatters for, say, "struct Foo" those will not
41 // match any type because of the way we strip qualifiers from typenames this
42 // method looks for the case where the user is adding a "class","struct","enum"
43 // or "union" Foo and strips the unnecessary qualifier
45  if (type.IsEmpty())
46  return type;
47 
48  std::string type_cstr(type.AsCString());
49  StringLexer type_lexer(type_cstr);
50 
51  type_lexer.AdvanceIf("class ");
52  type_lexer.AdvanceIf("enum ");
53  type_lexer.AdvanceIf("struct ");
54  type_lexer.AdvanceIf("union ");
55 
56  while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
57  ;
58 
59  return ConstString(type_lexer.GetUnlexed());
60 }
61 
62 template <typename KeyType, typename ValueType> class FormattersContainer;
63 
64 template <typename KeyType, typename ValueType> class FormatMap {
65 public:
66  typedef typename ValueType::SharedPointer ValueSP;
67  typedef std::vector<std::pair<KeyType, ValueSP>> MapType;
68  typedef typename MapType::iterator MapIterator;
69  typedef std::function<bool(const KeyType &, const ValueSP &)> ForEachCallback;
70 
72  : m_map(), m_map_mutex(), listener(lst) {}
73 
74  void Add(KeyType name, const ValueSP &entry) {
75  if (listener)
76  entry->GetRevision() = listener->GetCurrentRevision();
77  else
78  entry->GetRevision() = 0;
79 
80  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
81  Delete(name);
82  m_map.emplace_back(std::move(name), std::move(entry));
83  if (listener)
84  listener->Changed();
85  }
86 
87  bool Delete(const KeyType &name) {
88  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
89  for (MapIterator iter = m_map.begin(); iter != m_map.end(); ++iter)
90  if (iter->first == name) {
91  m_map.erase(iter);
92  if (listener)
93  listener->Changed();
94  return true;
95  }
96  return false;
97  }
98 
99  void Clear() {
100  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
101  m_map.clear();
102  if (listener)
103  listener->Changed();
104  }
105 
106  bool Get(const KeyType &name, ValueSP &entry) {
107  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
108  for (const auto &pos : m_map)
109  if (pos.first == name) {
110  entry = pos.second;
111  return true;
112  }
113  return false;
114  }
115 
116  void ForEach(ForEachCallback callback) {
117  if (callback) {
118  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
119  for (const auto &pos : m_map) {
120  const KeyType &type = pos.first;
121  if (!callback(type, pos.second))
122  break;
123  }
124  }
125  }
126 
127  uint32_t GetCount() { return m_map.size(); }
128 
129  ValueSP GetValueAtIndex(size_t index) {
130  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
131  if (index >= m_map.size())
132  return ValueSP();
133  return m_map[index].second;
134  }
135 
136  // If caller holds the mutex we could return a reference without copy ctor.
137  KeyType GetKeyAtIndex(size_t index) {
138  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
139  if (index >= m_map.size())
140  return {};
141  return m_map[index].first;
142  }
143 
144 protected:
145  MapType m_map;
146  std::recursive_mutex m_map_mutex;
148 
149  MapType &map() { return m_map; }
150 
151  std::recursive_mutex &mutex() { return m_map_mutex; }
152 
153  friend class FormattersContainer<KeyType, ValueType>;
154  friend class FormatManager;
155 };
156 
157 template <typename KeyType, typename ValueType> class FormattersContainer {
158 protected:
160 
161 public:
162  typedef typename BackEndType::MapType MapType;
163  typedef typename MapType::iterator MapIterator;
164  typedef KeyType MapKeyType;
165  typedef std::shared_ptr<ValueType> MapValueType;
166  typedef typename BackEndType::ForEachCallback ForEachCallback;
167  typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>>
169 
170  friend class TypeCategoryImpl;
171 
173  : m_format_map(lst), m_name(name) {}
174 
175  void Add(MapKeyType type, const MapValueType &entry) {
176  Add_Impl(std::move(type), entry, static_cast<KeyType *>(nullptr));
177  }
178 
179  bool Delete(ConstString type) {
180  return Delete_Impl(type, static_cast<KeyType *>(nullptr));
181  }
182 
183  bool Get(ValueObject &valobj, MapValueType &entry,
184  lldb::DynamicValueType use_dynamic) {
185  CompilerType ast_type(valobj.GetCompilerType());
186  bool ret = Get(valobj, ast_type, entry, use_dynamic);
187  if (ret)
188  entry = MapValueType(entry);
189  else
190  entry = MapValueType();
191  return ret;
192  }
193 
194  bool Get(ConstString type, MapValueType &entry) {
195  return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
196  }
197 
198  bool GetExact(ConstString type, MapValueType &entry) {
199  return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
200  }
201 
202  MapValueType GetAtIndex(size_t index) {
203  return m_format_map.GetValueAtIndex(index);
204  }
205 
206  lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
207  return GetTypeNameSpecifierAtIndex_Impl(index,
208  static_cast<KeyType *>(nullptr));
209  }
210 
211  void Clear() { m_format_map.Clear(); }
212 
213  void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
214 
215  uint32_t GetCount() { return m_format_map.GetCount(); }
216 
217 protected:
218  BackEndType m_format_map;
219  std::string m_name;
220 
221  FormattersContainer(const FormattersContainer &) = delete;
222  const FormattersContainer &operator=(const FormattersContainer &) = delete;
223 
224  void Add_Impl(MapKeyType type, const MapValueType &entry,
225  RegularExpression *dummy) {
226  m_format_map.Add(std::move(type), entry);
227  }
228 
229  void Add_Impl(ConstString type, const MapValueType &entry,
230  ConstString *dummy) {
231  m_format_map.Add(GetValidTypeName_Impl(type), entry);
232  }
233 
234  bool Delete_Impl(ConstString type, ConstString *dummy) {
235  return m_format_map.Delete(type);
236  }
237 
239  std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
240  MapIterator pos, end = m_format_map.map().end();
241  for (pos = m_format_map.map().begin(); pos != end; pos++) {
242  const RegularExpression &regex = pos->first;
243  if (type.GetStringRef() == regex.GetText()) {
244  m_format_map.map().erase(pos);
245  if (m_format_map.listener)
246  m_format_map.listener->Changed();
247  return true;
248  }
249  }
250  return false;
251  }
252 
253  bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
254  return m_format_map.Get(type, entry);
255  }
256 
257  bool GetExact_Impl(ConstString type, MapValueType &entry,
258  ConstString *dummy) {
259  return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
260  }
261 
262  lldb::TypeNameSpecifierImplSP
264  ConstString key = m_format_map.GetKeyAtIndex(index);
265  if (key)
266  return lldb::TypeNameSpecifierImplSP(
267  new TypeNameSpecifierImpl(key.GetStringRef(), false));
268  else
269  return lldb::TypeNameSpecifierImplSP();
270  }
271 
272  lldb::TypeNameSpecifierImplSP
274  RegularExpression regex = m_format_map.GetKeyAtIndex(index);
275  if (regex == RegularExpression())
276  return lldb::TypeNameSpecifierImplSP();
277  return lldb::TypeNameSpecifierImplSP(
278  new TypeNameSpecifierImpl(regex.GetText().str().c_str(), true));
279  }
280 
281  bool Get_Impl(ConstString key, MapValueType &value,
282  RegularExpression *dummy) {
283  llvm::StringRef key_str = key.GetStringRef();
284  std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
285  // Patterns are matched in reverse-chronological order.
286  for (const auto &pos : llvm::reverse(m_format_map.map())) {
287  const RegularExpression &regex = pos.first;
288  if (regex.Execute(key_str)) {
289  value = pos.second;
290  return true;
291  }
292  }
293  return false;
294  }
295 
296  bool GetExact_Impl(ConstString key, MapValueType &value,
297  RegularExpression *dummy) {
298  std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
299  for (const auto &pos : m_format_map.map()) {
300  const RegularExpression &regex = pos.first;
301  if (regex.GetText() == key.GetStringRef()) {
302  value = pos.second;
303  return true;
304  }
305  }
306  return false;
307  }
308 
309  bool Get(const FormattersMatchVector &candidates, MapValueType &entry) {
310  for (const FormattersMatchCandidate &candidate : candidates) {
311  if (Get(candidate.GetTypeName(), entry)) {
312  if (candidate.IsMatch(entry) == false) {
313  entry.reset();
314  continue;
315  } else {
316  return true;
317  }
318  }
319  }
320  return false;
321  }
322 };
323 
324 } // namespace lldb_private
325 
326 #endif // LLDB_DATAFORMATTERS_FORMATTERSCONTAINER_H
CompilerType GetCompilerType()
BackEndType::ForEachCallback ForEachCallback
A class that represents a running process on the host machine.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:223
std::recursive_mutex & mutex()
std::vector< std::pair< KeyType, ValueSP > > MapType
bool GetExact_Impl(ConstString key, MapValueType &value, RegularExpression *dummy)
bool Get(const FormattersMatchVector &candidates, MapValueType &entry)
void Add(MapKeyType type, const MapValueType &entry)
void Add_Impl(MapKeyType type, const MapValueType &entry, RegularExpression *dummy)
FormatMap(IFormatChangeListener *lst)
std::vector< FormattersMatchCandidate > FormattersMatchVector
Definition: FormatClasses.h:81
void ForEach(ForEachCallback callback)
FormattersContainer(std::string name, IFormatChangeListener *lst)
lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy)
bool Get(ConstString type, MapValueType &entry)
llvm::StringRef GetText() const
Access the regular expression text.
bool GetExact(ConstString type, MapValueType &entry)
void Add_Impl(ConstString type, const MapValueType &entry, ConstString *dummy)
FormatMap< KeyType, ValueType > BackEndType
virtual ~IFormatChangeListener()=default
std::shared_ptr< FormattersContainer< KeyType, ValueType > > SharedPointer
bool Get_Impl(ConstString key, MapValueType &value, RegularExpression *dummy)
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:232
void Add(KeyType name, const ValueSP &entry)
virtual uint32_t GetCurrentRevision()=0
static ConstString GetValidTypeName_Impl(ConstString type)
bool GetExact_Impl(ConstString type, MapValueType &entry, ConstString *dummy)
std::recursive_mutex m_map_mutex
bool Get(const KeyType &name, ValueSP &entry)
ValueSP GetValueAtIndex(size_t index)
A uniqued constant string class.
Definition: ConstString.h:40
MapType::iterator MapIterator
IFormatChangeListener * listener
lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index)
bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy)
Represents a generic type in a programming language.
Definition: CompilerType.h:33
std::shared_ptr< ValueType > MapValueType
bool Delete_Impl(ConstString type, RegularExpression *dummy)
std::function< bool(const KeyType &, const ValueSP &)> ForEachCallback
void ForEach(ForEachCallback callback)
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...
KeyType GetKeyAtIndex(size_t index)
lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex_Impl(size_t index, RegularExpression *dummy)
MapValueType GetAtIndex(size_t index)
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:334
bool Delete_Impl(ConstString type, ConstString *dummy)
bool Get(ValueObject &valobj, MapValueType &entry, lldb::DynamicValueType use_dynamic)
bool Delete(const KeyType &name)
ValueType::SharedPointer ValueSP