]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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
16 // Other libraries and framework includes
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/Type.h"
19 #include "clang/AST/DeclObjC.h"
20
21 // Project includes
22 #include "lldb/lldb-public.h"
23
24 #include "lldb/Core/Log.h"
25 #include "lldb/Core/RegularExpression.h"
26 #include "lldb/Core/ValueObject.h"
27
28 #include "lldb/DataFormatters/FormatClasses.h"
29 #include "lldb/DataFormatters/TypeFormat.h"
30 #include "lldb/DataFormatters/TypeSummary.h"
31 #include "lldb/DataFormatters/TypeSynthetic.h"
32
33 #include "lldb/Symbol/ClangASTContext.h"
34 #include "lldb/Symbol/ClangASTType.h"
35
36 #include "lldb/Target/ObjCLanguageRuntime.h"
37 #include "lldb/Target/Process.h"
38 #include "lldb/Target/StackFrame.h"
39 #include "lldb/Target/TargetList.h"
40
41 namespace lldb_private {
42     
43 // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization
44 // class DataVisualization is the high-level front-end of this feature
45 // clients should refer to that class as the entry-point into the data formatters
46 // unless they have a good reason to bypass it and prefer to use this file's objects directly
47 class IFormatChangeListener
48 {
49 public:
50     virtual void
51     Changed () = 0;
52     
53     virtual
54     ~IFormatChangeListener () {}
55     
56     virtual uint32_t
57     GetCurrentRevision () = 0;
58     
59 };
60     
61 static inline bool
62 IsWhitespace (char c)
63 {
64     return ( (c == ' ') || (c == '\t') || (c == '\v') || (c == '\f') );
65 }
66
67 static inline bool
68 HasPrefix (const char* str1, const char* str2)
69 {
70     return ( ::strstr(str1, str2) == str1 );
71 }
72     
73 // if the user tries to add formatters for, say, "struct Foo"
74 // those will not match any type because of the way we strip qualifiers from typenames
75 // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo
76 // and strips the unnecessary qualifier
77 static inline ConstString
78 GetValidTypeName_Impl (const ConstString& type)
79 {
80     int strip_len = 0;
81     
82     if ((bool)type == false)
83         return type;
84     
85     const char* type_cstr = type.AsCString();
86     
87     if ( HasPrefix(type_cstr, "class ") )
88         strip_len = 6;
89     else if ( HasPrefix(type_cstr, "enum ") )
90         strip_len = 5;
91     else if ( HasPrefix(type_cstr, "struct ") )
92         strip_len = 7;
93     else if ( HasPrefix(type_cstr, "union ") )
94         strip_len = 6;
95     
96     if (strip_len == 0)
97         return type;
98     
99     type_cstr += strip_len;
100     while (IsWhitespace(*type_cstr) && ++type_cstr)
101         ;
102     
103     return ConstString(type_cstr);
104 }
105     
106 template<typename KeyType, typename ValueType>
107 class FormattersContainer;
108
109 template<typename KeyType, typename ValueType>
110 class FormatMap
111 {
112 public:
113
114     typedef typename ValueType::SharedPointer ValueSP;
115     typedef std::map<KeyType, ValueSP> MapType;
116     typedef typename MapType::iterator MapIterator;
117     typedef bool(*CallbackType)(void*, KeyType, const ValueSP&);
118     
119     FormatMap(IFormatChangeListener* lst) :
120     m_map(),
121     m_map_mutex(Mutex::eMutexTypeRecursive),
122     listener(lst)
123     {
124     }
125     
126     void
127     Add(KeyType name,
128         const ValueSP& entry)
129     {
130         if (listener)
131             entry->GetRevision() = listener->GetCurrentRevision();
132         else
133             entry->GetRevision() = 0;
134
135         Mutex::Locker locker(m_map_mutex);
136         m_map[name] = entry;
137         if (listener)
138             listener->Changed();
139     }
140     
141     bool
142     Delete (KeyType name)
143     {
144         Mutex::Locker locker(m_map_mutex);
145         MapIterator iter = m_map.find(name);
146         if (iter == m_map.end())
147             return false;
148         m_map.erase(name);
149         if (listener)
150             listener->Changed();
151         return true;
152     }
153     
154     void
155     Clear ()
156     {
157         Mutex::Locker locker(m_map_mutex);
158         m_map.clear();
159         if (listener)
160             listener->Changed();
161     }
162     
163     bool
164     Get(KeyType name,
165         ValueSP& entry)
166     {
167         Mutex::Locker locker(m_map_mutex);
168         MapIterator iter = m_map.find(name);
169         if (iter == m_map.end())
170             return false;
171         entry = iter->second;
172         return true;
173     }
174     
175     void
176     LoopThrough (CallbackType callback, void* param)
177     {
178         if (callback)
179         {
180             Mutex::Locker locker(m_map_mutex);
181             MapIterator pos, end = m_map.end();
182             for (pos = m_map.begin(); pos != end; pos++)
183             {
184                 KeyType type = pos->first;
185                 if (!callback(param, type, pos->second))
186                     break;
187             }
188         }
189     }
190     
191     uint32_t
192     GetCount ()
193     {
194         return m_map.size();
195     }
196     
197     ValueSP
198     GetValueAtIndex (size_t index)
199     {
200         Mutex::Locker locker(m_map_mutex);
201         MapIterator iter = m_map.begin();
202         MapIterator end = m_map.end();
203         while (index > 0)
204         {
205             iter++;
206             index--;
207             if (end == iter)
208                 return ValueSP();
209         }
210         return iter->second;
211     }
212     
213     KeyType
214     GetKeyAtIndex (size_t index)
215     {
216         Mutex::Locker locker(m_map_mutex);
217         MapIterator iter = m_map.begin();
218         MapIterator end = m_map.end();
219         while (index > 0)
220         {
221             iter++;
222             index--;
223             if (end == iter)
224                 return KeyType();
225         }
226         return iter->first;
227     }
228     
229 protected:
230     MapType m_map;    
231     Mutex m_map_mutex;
232     IFormatChangeListener* listener;
233     
234     MapType&
235     map ()
236     {
237         return m_map;
238     }
239     
240     Mutex&
241     mutex ()
242     {
243         return m_map_mutex;
244     }
245     
246     friend class FormattersContainer<KeyType, ValueType>;
247     friend class FormatManager;
248     
249 };
250     
251 template<typename KeyType, typename ValueType>
252 class FormattersContainer
253 {
254 protected:
255     typedef FormatMap<KeyType,ValueType> BackEndType;
256     
257 public:
258     typedef typename BackEndType::MapType MapType;
259     typedef typename MapType::iterator MapIterator;
260     typedef typename MapType::key_type MapKeyType;
261     typedef typename MapType::mapped_type MapValueType;
262     typedef typename BackEndType::CallbackType CallbackType;
263     typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType> > SharedPointer;
264     
265     friend class TypeCategoryImpl;
266
267     FormattersContainer(std::string name,
268                     IFormatChangeListener* lst) :
269     m_format_map(lst),
270     m_name(name),
271     m_id_cs(ConstString("id"))
272     {
273     }
274     
275     void
276     Add (const MapKeyType &type, const MapValueType& entry)
277     {
278         Add_Impl(type, entry, (KeyType*)NULL);
279     }
280     
281     bool
282     Delete (ConstString type)
283     {
284         return Delete_Impl(type, (KeyType*)NULL);
285     }
286         
287     bool
288     Get(ValueObject& valobj,
289         MapValueType& entry,
290         lldb::DynamicValueType use_dynamic,
291         uint32_t* why = NULL)
292     {
293         uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
294         ClangASTType ast_type(valobj.GetClangType());
295         bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
296         if (ret)
297             entry = MapValueType(entry);
298         else
299             entry = MapValueType();        
300         if (why)
301             *why = value;
302         return ret;
303     }
304     
305     bool
306     Get (ConstString type, MapValueType& entry)
307     {
308         return Get_Impl(type, entry, (KeyType*)NULL);
309     }
310     
311     bool
312     GetExact (ConstString type, MapValueType& entry)
313     {
314         return GetExact_Impl(type, entry, (KeyType*)NULL);
315     }
316     
317     MapValueType
318     GetAtIndex (size_t index)
319     {
320         return m_format_map.GetValueAtIndex(index);
321     }
322     
323     lldb::TypeNameSpecifierImplSP
324     GetTypeNameSpecifierAtIndex (size_t index)
325     {
326         return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL);
327     }
328     
329     void
330     Clear ()
331     {
332         m_format_map.Clear();
333     }
334     
335     void
336     LoopThrough (CallbackType callback, void* param)
337     {
338         m_format_map.LoopThrough(callback,param);
339     }
340     
341     uint32_t
342     GetCount ()
343     {
344         return m_format_map.GetCount();
345     }
346     
347 protected:
348         
349     BackEndType m_format_map;
350     
351     std::string m_name;
352     
353     DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
354     
355     ConstString m_id_cs;
356                            
357     void
358     Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy)
359     {
360        m_format_map.Add(type,entry);
361     }
362
363     void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy)
364     {
365        m_format_map.Add(GetValidTypeName_Impl(type), entry);
366     }
367
368     bool
369     Delete_Impl (ConstString type, ConstString *dummy)
370     {
371        return m_format_map.Delete(type);
372     }
373
374     bool
375     Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy)
376     {
377        Mutex& x_mutex = m_format_map.mutex();
378         lldb_private::Mutex::Locker locker(x_mutex);
379        MapIterator pos, end = m_format_map.map().end();
380        for (pos = m_format_map.map().begin(); pos != end; pos++)
381        {
382            lldb::RegularExpressionSP regex = pos->first;
383            if ( ::strcmp(type.AsCString(),regex->GetText()) == 0)
384            {
385                m_format_map.map().erase(pos);
386                if (m_format_map.listener)
387                    m_format_map.listener->Changed();
388                return true;
389            }
390        }
391        return false;
392     }    
393
394     bool
395     Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
396     {
397        return m_format_map.Get(type, entry);
398     }
399
400     bool
401     GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
402     {
403         return Get_Impl(type,entry, (KeyType*)0);
404     }
405     
406     lldb::TypeNameSpecifierImplSP
407     GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy)
408     {
409         ConstString key = m_format_map.GetKeyAtIndex(index);
410         if (key)
411             return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(),
412                                                                            false));
413         else
414             return lldb::TypeNameSpecifierImplSP();
415     }
416     
417     lldb::TypeNameSpecifierImplSP
418     GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
419     {
420         lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
421         if (regex.get() == NULL)
422             return lldb::TypeNameSpecifierImplSP();
423         return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
424                                                                        true));
425     }
426
427     bool
428     Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
429     {
430        const char* key_cstr = key.AsCString();
431        if (!key_cstr)
432            return false;
433        Mutex& x_mutex = m_format_map.mutex();
434        lldb_private::Mutex::Locker locker(x_mutex);
435        MapIterator pos, end = m_format_map.map().end();
436        for (pos = m_format_map.map().begin(); pos != end; pos++)
437        {
438            lldb::RegularExpressionSP regex = pos->first;
439            if (regex->Execute(key_cstr))
440            {
441                value = pos->second;
442                return true;
443            }
444        }
445        return false;
446     }
447     
448     bool
449     GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
450     {
451         Mutex& x_mutex = m_format_map.mutex();
452         lldb_private::Mutex::Locker locker(x_mutex);
453         MapIterator pos, end = m_format_map.map().end();
454         for (pos = m_format_map.map().begin(); pos != end; pos++)
455         {
456             lldb::RegularExpressionSP regex = pos->first;
457             if (strcmp(regex->GetText(),key.AsCString()) == 0)
458             {
459                 value = pos->second;
460                 return true;
461             }
462         }
463         return false;
464     }
465
466     bool
467     Get (const FormattersMatchVector& candidates,
468          MapValueType& entry,
469          uint32_t *reason)
470     {
471         for (const FormattersMatchCandidate& candidate : candidates)
472         {
473             // FIXME: could we do the IsMatch() check first?
474             if (Get(candidate.GetTypeName(),entry))
475             {
476                 if (candidate.IsMatch(entry) == false)
477                 {
478                     entry.reset();
479                     continue;
480                 }
481                 else
482                 {
483                     if(reason)
484                         *reason = candidate.GetReason();
485                     return true;
486                 }
487             }
488         }
489         return false;
490     }
491 };
492
493 } // namespace lldb_private
494
495 #endif  // lldb_FormattersContainer_h_