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