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