FormattersContainer.h revision 314564
1296417Sdim//===-- FormattersContainer.h -----------------------------------*- C++ -*-===//
2262182Semaste//
3262182Semaste//                     The LLVM Compiler Infrastructure
4262182Semaste//
5262182Semaste// This file is distributed under the University of Illinois Open Source
6262182Semaste// License. See LICENSE.TXT for details.
7262182Semaste//
8262182Semaste//===----------------------------------------------------------------------===//
9262182Semaste
10262182Semaste#ifndef lldb_FormattersContainer_h_
11262182Semaste#define lldb_FormattersContainer_h_
12262182Semaste
13262182Semaste// C Includes
14262182Semaste// C++ Includes
15296417Sdim#include <functional>
16296417Sdim#include <map>
17296417Sdim#include <memory>
18309124Sdim#include <mutex>
19296417Sdim#include <string>
20262182Semaste
21262182Semaste// Other libraries and framework includes
22262182Semaste// Project includes
23262182Semaste#include "lldb/lldb-public.h"
24262182Semaste
25262182Semaste#include "lldb/Core/RegularExpression.h"
26262182Semaste#include "lldb/Core/ValueObject.h"
27262182Semaste#include "lldb/DataFormatters/FormatClasses.h"
28262182Semaste#include "lldb/DataFormatters/TypeFormat.h"
29262182Semaste#include "lldb/DataFormatters/TypeSummary.h"
30262182Semaste#include "lldb/DataFormatters/TypeSynthetic.h"
31280031Sdim#include "lldb/DataFormatters/TypeValidator.h"
32296417Sdim#include "lldb/Symbol/CompilerType.h"
33280031Sdim#include "lldb/Utility/StringLexer.h"
34280031Sdim
35262182Semastenamespace lldb_private {
36314564Sdim
37314564Sdimclass IFormatChangeListener {
38262182Semastepublic:
39314564Sdim  virtual ~IFormatChangeListener() = default;
40296417Sdim
41314564Sdim  virtual void Changed() = 0;
42296417Sdim
43314564Sdim  virtual uint32_t GetCurrentRevision() = 0;
44262182Semaste};
45314564Sdim
46262182Semaste// if the user tries to add formatters for, say, "struct Foo"
47314564Sdim// those will not match any type because of the way we strip qualifiers from
48314564Sdim// typenames
49314564Sdim// this method looks for the case where the user is adding a
50314564Sdim// "class","struct","enum" or "union" Foo
51262182Semaste// and strips the unnecessary qualifier
52314564Sdimstatic inline ConstString GetValidTypeName_Impl(const ConstString &type) {
53314564Sdim  if (type.IsEmpty())
54314564Sdim    return type;
55314564Sdim
56314564Sdim  std::string type_cstr(type.AsCString());
57314564Sdim  lldb_utility::StringLexer type_lexer(type_cstr);
58314564Sdim
59314564Sdim  type_lexer.AdvanceIf("class ");
60314564Sdim  type_lexer.AdvanceIf("enum ");
61314564Sdim  type_lexer.AdvanceIf("struct ");
62314564Sdim  type_lexer.AdvanceIf("union ");
63314564Sdim
64314564Sdim  while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
65314564Sdim    ;
66314564Sdim
67314564Sdim  return ConstString(type_lexer.GetUnlexed());
68262182Semaste}
69280031Sdim
70314564Sdimtemplate <typename KeyType, typename ValueType> class FormattersContainer;
71262182Semaste
72314564Sdimtemplate <typename KeyType, typename ValueType> class FormatMap {
73262182Semastepublic:
74314564Sdim  typedef typename ValueType::SharedPointer ValueSP;
75314564Sdim  typedef std::map<KeyType, ValueSP> MapType;
76314564Sdim  typedef typename MapType::iterator MapIterator;
77314564Sdim  typedef std::function<bool(KeyType, const ValueSP &)> ForEachCallback;
78309124Sdim
79314564Sdim  FormatMap(IFormatChangeListener *lst)
80314564Sdim      : m_map(), m_map_mutex(), listener(lst) {}
81309124Sdim
82314564Sdim  void Add(KeyType name, const ValueSP &entry) {
83314564Sdim    if (listener)
84314564Sdim      entry->GetRevision() = listener->GetCurrentRevision();
85314564Sdim    else
86314564Sdim      entry->GetRevision() = 0;
87262182Semaste
88314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
89314564Sdim    m_map[name] = entry;
90314564Sdim    if (listener)
91314564Sdim      listener->Changed();
92314564Sdim  }
93309124Sdim
94314564Sdim  bool Delete(KeyType name) {
95314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
96314564Sdim    MapIterator iter = m_map.find(name);
97314564Sdim    if (iter == m_map.end())
98314564Sdim      return false;
99314564Sdim    m_map.erase(name);
100314564Sdim    if (listener)
101314564Sdim      listener->Changed();
102314564Sdim    return true;
103314564Sdim  }
104309124Sdim
105314564Sdim  void Clear() {
106314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
107314564Sdim    m_map.clear();
108314564Sdim    if (listener)
109314564Sdim      listener->Changed();
110314564Sdim  }
111309124Sdim
112314564Sdim  bool Get(KeyType name, ValueSP &entry) {
113314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
114314564Sdim    MapIterator iter = m_map.find(name);
115314564Sdim    if (iter == m_map.end())
116314564Sdim      return false;
117314564Sdim    entry = iter->second;
118314564Sdim    return true;
119314564Sdim  }
120309124Sdim
121314564Sdim  void ForEach(ForEachCallback callback) {
122314564Sdim    if (callback) {
123314564Sdim      std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
124314564Sdim      MapIterator pos, end = m_map.end();
125314564Sdim      for (pos = m_map.begin(); pos != end; pos++) {
126314564Sdim        KeyType type = pos->first;
127314564Sdim        if (!callback(type, pos->second))
128314564Sdim          break;
129314564Sdim      }
130262182Semaste    }
131314564Sdim  }
132309124Sdim
133314564Sdim  uint32_t GetCount() { return m_map.size(); }
134309124Sdim
135314564Sdim  ValueSP GetValueAtIndex(size_t index) {
136314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
137314564Sdim    MapIterator iter = m_map.begin();
138314564Sdim    MapIterator end = m_map.end();
139314564Sdim    while (index > 0) {
140314564Sdim      iter++;
141314564Sdim      index--;
142314564Sdim      if (end == iter)
143314564Sdim        return ValueSP();
144262182Semaste    }
145314564Sdim    return iter->second;
146314564Sdim  }
147309124Sdim
148314564Sdim  KeyType GetKeyAtIndex(size_t index) {
149314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
150314564Sdim    MapIterator iter = m_map.begin();
151314564Sdim    MapIterator end = m_map.end();
152314564Sdim    while (index > 0) {
153314564Sdim      iter++;
154314564Sdim      index--;
155314564Sdim      if (end == iter)
156314564Sdim        return KeyType();
157262182Semaste    }
158314564Sdim    return iter->first;
159314564Sdim  }
160309124Sdim
161262182Semasteprotected:
162314564Sdim  MapType m_map;
163314564Sdim  std::recursive_mutex m_map_mutex;
164314564Sdim  IFormatChangeListener *listener;
165309124Sdim
166314564Sdim  MapType &map() { return m_map; }
167309124Sdim
168314564Sdim  std::recursive_mutex &mutex() { return m_map_mutex; }
169309124Sdim
170314564Sdim  friend class FormattersContainer<KeyType, ValueType>;
171314564Sdim  friend class FormatManager;
172262182Semaste};
173314564Sdim
174314564Sdimtemplate <typename KeyType, typename ValueType> class FormattersContainer {
175262182Semasteprotected:
176314564Sdim  typedef FormatMap<KeyType, ValueType> BackEndType;
177314564Sdim
178262182Semastepublic:
179314564Sdim  typedef typename BackEndType::MapType MapType;
180314564Sdim  typedef typename MapType::iterator MapIterator;
181314564Sdim  typedef typename MapType::key_type MapKeyType;
182314564Sdim  typedef typename MapType::mapped_type MapValueType;
183314564Sdim  typedef typename BackEndType::ForEachCallback ForEachCallback;
184314564Sdim  typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>>
185314564Sdim      SharedPointer;
186262182Semaste
187314564Sdim  friend class TypeCategoryImpl;
188314564Sdim
189314564Sdim  FormattersContainer(std::string name, IFormatChangeListener *lst)
190314564Sdim      : m_format_map(lst), m_name(name) {}
191314564Sdim
192314564Sdim  void Add(const MapKeyType &type, const MapValueType &entry) {
193314564Sdim    Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
194314564Sdim  }
195314564Sdim
196314564Sdim  bool Delete(ConstString type) {
197314564Sdim    return Delete_Impl(type, static_cast<KeyType *>(nullptr));
198314564Sdim  }
199314564Sdim
200314564Sdim  bool Get(ValueObject &valobj, MapValueType &entry,
201314564Sdim           lldb::DynamicValueType use_dynamic, uint32_t *why = nullptr) {
202314564Sdim    uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
203314564Sdim    CompilerType ast_type(valobj.GetCompilerType());
204314564Sdim    bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
205314564Sdim    if (ret)
206314564Sdim      entry = MapValueType(entry);
207314564Sdim    else
208314564Sdim      entry = MapValueType();
209314564Sdim    if (why)
210314564Sdim      *why = value;
211314564Sdim    return ret;
212314564Sdim  }
213314564Sdim
214314564Sdim  bool Get(ConstString type, MapValueType &entry) {
215314564Sdim    return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
216314564Sdim  }
217314564Sdim
218314564Sdim  bool GetExact(ConstString type, MapValueType &entry) {
219314564Sdim    return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
220314564Sdim  }
221314564Sdim
222314564Sdim  MapValueType GetAtIndex(size_t index) {
223314564Sdim    return m_format_map.GetValueAtIndex(index);
224314564Sdim  }
225314564Sdim
226314564Sdim  lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
227314564Sdim    return GetTypeNameSpecifierAtIndex_Impl(index,
228314564Sdim                                            static_cast<KeyType *>(nullptr));
229314564Sdim  }
230314564Sdim
231314564Sdim  void Clear() { m_format_map.Clear(); }
232314564Sdim
233314564Sdim  void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
234314564Sdim
235314564Sdim  uint32_t GetCount() { return m_format_map.GetCount(); }
236314564Sdim
237262182Semasteprotected:
238314564Sdim  BackEndType m_format_map;
239314564Sdim  std::string m_name;
240262182Semaste
241314564Sdim  DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
242262182Semaste
243314564Sdim  void Add_Impl(const MapKeyType &type, const MapValueType &entry,
244314564Sdim                lldb::RegularExpressionSP *dummy) {
245314564Sdim    m_format_map.Add(type, entry);
246314564Sdim  }
247262182Semaste
248314564Sdim  void Add_Impl(const ConstString &type, const MapValueType &entry,
249314564Sdim                ConstString *dummy) {
250314564Sdim    m_format_map.Add(GetValidTypeName_Impl(type), entry);
251314564Sdim  }
252262182Semaste
253314564Sdim  bool Delete_Impl(ConstString type, ConstString *dummy) {
254314564Sdim    return m_format_map.Delete(type);
255314564Sdim  }
256262182Semaste
257314564Sdim  bool Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) {
258314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
259314564Sdim    MapIterator pos, end = m_format_map.map().end();
260314564Sdim    for (pos = m_format_map.map().begin(); pos != end; pos++) {
261314564Sdim      lldb::RegularExpressionSP regex = pos->first;
262314564Sdim      if (type.GetStringRef() == regex->GetText()) {
263314564Sdim        m_format_map.map().erase(pos);
264314564Sdim        if (m_format_map.listener)
265314564Sdim          m_format_map.listener->Changed();
266314564Sdim        return true;
267314564Sdim      }
268262182Semaste    }
269314564Sdim    return false;
270314564Sdim  }
271262182Semaste
272314564Sdim  bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
273314564Sdim    return m_format_map.Get(type, entry);
274314564Sdim  }
275314564Sdim
276314564Sdim  bool GetExact_Impl(ConstString type, MapValueType &entry,
277314564Sdim                     ConstString *dummy) {
278314564Sdim    return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
279314564Sdim  }
280314564Sdim
281314564Sdim  lldb::TypeNameSpecifierImplSP
282314564Sdim  GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
283314564Sdim    ConstString key = m_format_map.GetKeyAtIndex(index);
284314564Sdim    if (key)
285314564Sdim      return lldb::TypeNameSpecifierImplSP(
286314564Sdim          new TypeNameSpecifierImpl(key.AsCString(), false));
287314564Sdim    else
288314564Sdim      return lldb::TypeNameSpecifierImplSP();
289314564Sdim  }
290314564Sdim
291314564Sdim  lldb::TypeNameSpecifierImplSP
292314564Sdim  GetTypeNameSpecifierAtIndex_Impl(size_t index,
293314564Sdim                                   lldb::RegularExpressionSP *dummy) {
294314564Sdim    lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
295314564Sdim    if (regex.get() == nullptr)
296314564Sdim      return lldb::TypeNameSpecifierImplSP();
297314564Sdim    return lldb::TypeNameSpecifierImplSP(
298314564Sdim        new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true));
299314564Sdim  }
300314564Sdim
301314564Sdim  bool Get_Impl(ConstString key, MapValueType &value,
302314564Sdim                lldb::RegularExpressionSP *dummy) {
303314564Sdim    llvm::StringRef key_str = key.GetStringRef();
304314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
305314564Sdim    MapIterator pos, end = m_format_map.map().end();
306314564Sdim    for (pos = m_format_map.map().begin(); pos != end; pos++) {
307314564Sdim      lldb::RegularExpressionSP regex = pos->first;
308314564Sdim      if (regex->Execute(key_str)) {
309314564Sdim        value = pos->second;
310314564Sdim        return true;
311314564Sdim      }
312262182Semaste    }
313314564Sdim    return false;
314314564Sdim  }
315309124Sdim
316314564Sdim  bool GetExact_Impl(ConstString key, MapValueType &value,
317314564Sdim                     lldb::RegularExpressionSP *dummy) {
318314564Sdim    std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
319314564Sdim    MapIterator pos, end = m_format_map.map().end();
320314564Sdim    for (pos = m_format_map.map().begin(); pos != end; pos++) {
321314564Sdim      lldb::RegularExpressionSP regex = pos->first;
322314564Sdim      if (regex->GetText() == key.GetStringRef()) {
323314564Sdim        value = pos->second;
324314564Sdim        return true;
325314564Sdim      }
326262182Semaste    }
327314564Sdim    return false;
328314564Sdim  }
329262182Semaste
330314564Sdim  bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
331314564Sdim           uint32_t *reason) {
332314564Sdim    for (const FormattersMatchCandidate &candidate : candidates) {
333314564Sdim      if (Get(candidate.GetTypeName(), entry)) {
334314564Sdim        if (candidate.IsMatch(entry) == false) {
335314564Sdim          entry.reset();
336314564Sdim          continue;
337314564Sdim        } else {
338314564Sdim          if (reason)
339314564Sdim            *reason = candidate.GetReason();
340314564Sdim          return true;
341262182Semaste        }
342314564Sdim      }
343262182Semaste    }
344314564Sdim    return false;
345314564Sdim  }
346262182Semaste};
347262182Semaste
348262182Semaste} // namespace lldb_private
349262182Semaste
350296417Sdim#endif // lldb_FormattersContainer_h_
351