]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
MFV r304732.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / DataFormatters / FormattersContainer.h
1 //===-- FormattersContainer.h -----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef lldb_FormattersContainer_h_
11 #define lldb_FormattersContainer_h_
12
13 // C Includes
14 // C++ Includes
15 #include <functional>
16 #include <map>
17 #include <memory>
18 #include <string>
19
20 // Other libraries and framework includes
21 // Project includes
22 #include "lldb/lldb-public.h"
23
24 #include "lldb/Core/RegularExpression.h"
25 #include "lldb/Core/ValueObject.h"
26 #include "lldb/DataFormatters/FormatClasses.h"
27 #include "lldb/DataFormatters/TypeFormat.h"
28 #include "lldb/DataFormatters/TypeSummary.h"
29 #include "lldb/DataFormatters/TypeSynthetic.h"
30 #include "lldb/DataFormatters/TypeValidator.h"
31 #include "lldb/Symbol/CompilerType.h"
32 #include "lldb/Utility/StringLexer.h"
33
34 namespace lldb_private {
35     
36 class IFormatChangeListener
37 {
38 public:
39     virtual
40     ~IFormatChangeListener() = default;
41
42     virtual void
43     Changed () = 0;
44
45     virtual uint32_t
46     GetCurrentRevision () = 0;
47 };
48     
49 // if the user tries to add formatters for, say, "struct Foo"
50 // those will not match any type because of the way we strip qualifiers from typenames
51 // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo
52 // and strips the unnecessary qualifier
53 static inline ConstString
54 GetValidTypeName_Impl (const ConstString& type)
55 {
56     if (type.IsEmpty())
57         return type;
58     
59     std::string type_cstr(type.AsCString());
60     lldb_utility::StringLexer type_lexer(type_cstr);
61     
62     type_lexer.AdvanceIf("class ");
63     type_lexer.AdvanceIf("enum ");
64     type_lexer.AdvanceIf("struct ");
65     type_lexer.AdvanceIf("union ");
66     
67     while (type_lexer.NextIf({' ','\t','\v','\f'}).first)
68         ;
69     
70     return ConstString(type_lexer.GetUnlexed());
71 }
72
73 template<typename KeyType, typename ValueType>
74 class FormattersContainer;
75
76 template<typename KeyType, typename ValueType>
77 class FormatMap
78 {
79 public:
80     typedef typename ValueType::SharedPointer ValueSP;
81     typedef std::map<KeyType, ValueSP> MapType;
82     typedef typename MapType::iterator MapIterator;
83     typedef std::function<bool(KeyType, const ValueSP&)> ForEachCallback;
84     
85     FormatMap(IFormatChangeListener* lst) :
86     m_map(),
87     m_map_mutex(Mutex::eMutexTypeRecursive),
88     listener(lst)
89     {
90     }
91     
92     void
93     Add(KeyType name,
94         const ValueSP& entry)
95     {
96         if (listener)
97             entry->GetRevision() = listener->GetCurrentRevision();
98         else
99             entry->GetRevision() = 0;
100
101         Mutex::Locker locker(m_map_mutex);
102         m_map[name] = entry;
103         if (listener)
104             listener->Changed();
105     }
106     
107     bool
108     Delete (KeyType name)
109     {
110         Mutex::Locker locker(m_map_mutex);
111         MapIterator iter = m_map.find(name);
112         if (iter == m_map.end())
113             return false;
114         m_map.erase(name);
115         if (listener)
116             listener->Changed();
117         return true;
118     }
119     
120     void
121     Clear ()
122     {
123         Mutex::Locker locker(m_map_mutex);
124         m_map.clear();
125         if (listener)
126             listener->Changed();
127     }
128     
129     bool
130     Get(KeyType name,
131         ValueSP& entry)
132     {
133         Mutex::Locker locker(m_map_mutex);
134         MapIterator iter = m_map.find(name);
135         if (iter == m_map.end())
136             return false;
137         entry = iter->second;
138         return true;
139     }
140     
141     void
142     ForEach (ForEachCallback callback)
143     {
144         if (callback)
145         {
146             Mutex::Locker locker(m_map_mutex);
147             MapIterator pos, end = m_map.end();
148             for (pos = m_map.begin(); pos != end; pos++)
149             {
150                 KeyType type = pos->first;
151                 if (!callback(type, pos->second))
152                     break;
153             }
154         }
155     }
156     
157     uint32_t
158     GetCount ()
159     {
160         return m_map.size();
161     }
162     
163     ValueSP
164     GetValueAtIndex (size_t index)
165     {
166         Mutex::Locker locker(m_map_mutex);
167         MapIterator iter = m_map.begin();
168         MapIterator end = m_map.end();
169         while (index > 0)
170         {
171             iter++;
172             index--;
173             if (end == iter)
174                 return ValueSP();
175         }
176         return iter->second;
177     }
178     
179     KeyType
180     GetKeyAtIndex (size_t index)
181     {
182         Mutex::Locker locker(m_map_mutex);
183         MapIterator iter = m_map.begin();
184         MapIterator end = m_map.end();
185         while (index > 0)
186         {
187             iter++;
188             index--;
189             if (end == iter)
190                 return KeyType();
191         }
192         return iter->first;
193     }
194     
195 protected:
196     MapType m_map;    
197     Mutex m_map_mutex;
198     IFormatChangeListener* listener;
199     
200     MapType&
201     map ()
202     {
203         return m_map;
204     }
205     
206     Mutex&
207     mutex ()
208     {
209         return m_map_mutex;
210     }
211     
212     friend class FormattersContainer<KeyType, ValueType>;
213     friend class FormatManager;
214 };
215     
216 template<typename KeyType, typename ValueType>
217 class FormattersContainer
218 {
219 protected:
220     typedef FormatMap<KeyType,ValueType> BackEndType;
221     
222 public:
223     typedef typename BackEndType::MapType MapType;
224     typedef typename MapType::iterator MapIterator;
225     typedef typename MapType::key_type MapKeyType;
226     typedef typename MapType::mapped_type MapValueType;
227     typedef typename BackEndType::ForEachCallback ForEachCallback;
228     typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType> > SharedPointer;
229     
230     friend class TypeCategoryImpl;
231
232     FormattersContainer(std::string name,
233                     IFormatChangeListener* lst) :
234     m_format_map(lst),
235     m_name(name)
236     {
237     }
238     
239     void
240     Add (const MapKeyType &type, const MapValueType& entry)
241     {
242         Add_Impl(type, entry, static_cast<KeyType*>(nullptr));
243     }
244     
245     bool
246     Delete (ConstString type)
247     {
248         return Delete_Impl(type, static_cast<KeyType*>(nullptr));
249     }
250         
251     bool
252     Get(ValueObject& valobj,
253         MapValueType& entry,
254         lldb::DynamicValueType use_dynamic,
255         uint32_t* why = nullptr)
256     {
257         uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
258         CompilerType ast_type(valobj.GetCompilerType());
259         bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
260         if (ret)
261             entry = MapValueType(entry);
262         else
263             entry = MapValueType();        
264         if (why)
265             *why = value;
266         return ret;
267     }
268     
269     bool
270     Get (ConstString type, MapValueType& entry)
271     {
272         return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
273     }
274     
275     bool
276     GetExact (ConstString type, MapValueType& entry)
277     {
278         return GetExact_Impl(type, entry, static_cast<KeyType*>(nullptr));
279     }
280     
281     MapValueType
282     GetAtIndex (size_t index)
283     {
284         return m_format_map.GetValueAtIndex(index);
285     }
286     
287     lldb::TypeNameSpecifierImplSP
288     GetTypeNameSpecifierAtIndex (size_t index)
289     {
290         return GetTypeNameSpecifierAtIndex_Impl(index, static_cast<KeyType*>(nullptr));
291     }
292     
293     void
294     Clear ()
295     {
296         m_format_map.Clear();
297     }
298     
299     void
300     ForEach (ForEachCallback callback)
301     {
302         m_format_map.ForEach(callback);
303     }
304     
305     uint32_t
306     GetCount ()
307     {
308         return m_format_map.GetCount();
309     }
310     
311 protected:
312     BackEndType m_format_map;
313     std::string m_name;
314     
315     DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
316     
317     void
318     Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy)
319     {
320        m_format_map.Add(type,entry);
321     }
322
323     void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy)
324     {
325        m_format_map.Add(GetValidTypeName_Impl(type), entry);
326     }
327
328     bool
329     Delete_Impl (ConstString type, ConstString *dummy)
330     {
331        return m_format_map.Delete(type);
332     }
333
334     bool
335     Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy)
336     {
337        Mutex& x_mutex = m_format_map.mutex();
338         lldb_private::Mutex::Locker locker(x_mutex);
339        MapIterator pos, end = m_format_map.map().end();
340        for (pos = m_format_map.map().begin(); pos != end; pos++)
341        {
342            lldb::RegularExpressionSP regex = pos->first;
343            if ( ::strcmp(type.AsCString(),regex->GetText()) == 0)
344            {
345                m_format_map.map().erase(pos);
346                if (m_format_map.listener)
347                    m_format_map.listener->Changed();
348                return true;
349            }
350        }
351        return false;
352     }    
353
354     bool
355     Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
356     {
357        return m_format_map.Get(type, entry);
358     }
359
360     bool
361     GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
362     {
363         return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
364     }
365     
366     lldb::TypeNameSpecifierImplSP
367     GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy)
368     {
369         ConstString key = m_format_map.GetKeyAtIndex(index);
370         if (key)
371             return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(),
372                                                                            false));
373         else
374             return lldb::TypeNameSpecifierImplSP();
375     }
376     
377     lldb::TypeNameSpecifierImplSP
378     GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
379     {
380         lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
381         if (regex.get() == nullptr)
382             return lldb::TypeNameSpecifierImplSP();
383         return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
384                                                                        true));
385     }
386
387     bool
388     Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
389     {
390        const char* key_cstr = key.AsCString();
391        if (!key_cstr)
392            return false;
393        Mutex& x_mutex = m_format_map.mutex();
394        lldb_private::Mutex::Locker locker(x_mutex);
395        MapIterator pos, end = m_format_map.map().end();
396        for (pos = m_format_map.map().begin(); pos != end; pos++)
397        {
398            lldb::RegularExpressionSP regex = pos->first;
399            if (regex->Execute(key_cstr))
400            {
401                value = pos->second;
402                return true;
403            }
404        }
405        return false;
406     }
407     
408     bool
409     GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
410     {
411         Mutex& x_mutex = m_format_map.mutex();
412         lldb_private::Mutex::Locker locker(x_mutex);
413         MapIterator pos, end = m_format_map.map().end();
414         for (pos = m_format_map.map().begin(); pos != end; pos++)
415         {
416             lldb::RegularExpressionSP regex = pos->first;
417             if (strcmp(regex->GetText(),key.AsCString()) == 0)
418             {
419                 value = pos->second;
420                 return true;
421             }
422         }
423         return false;
424     }
425
426     bool
427     Get (const FormattersMatchVector& candidates,
428          MapValueType& entry,
429          uint32_t *reason)
430     {
431         for (const FormattersMatchCandidate& candidate : candidates)
432         {
433             if (Get(candidate.GetTypeName(),entry))
434             {
435                 if (candidate.IsMatch(entry) == false)
436                 {
437                     entry.reset();
438                     continue;
439                 }
440                 else
441                 {
442                     if(reason)
443                         *reason = candidate.GetReason();
444                     return true;
445                 }
446             }
447         }
448         return false;
449     }
450 };
451
452 } // namespace lldb_private
453
454 #endif // lldb_FormattersContainer_h_