TypeCategoryMap.cpp revision 263367
1//===-- TypeCategoryMap.cpp ----------------------------------------*- 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#include "lldb/lldb-python.h"
11
12#include "lldb/DataFormatters/TypeCategoryMap.h"
13
14#include "lldb/DataFormatters/FormatClasses.h"
15#include "lldb/DataFormatters/FormatManager.h"
16
17// C Includes
18// C++ Includes
19// Other libraries and framework includes
20// Project includes
21
22using namespace lldb;
23using namespace lldb_private;
24
25TypeCategoryMap::TypeCategoryMap (IFormatChangeListener* lst) :
26m_map_mutex(Mutex::eMutexTypeRecursive),
27listener(lst),
28m_map(),
29m_active_categories()
30{
31    ConstString default_cs("default");
32    lldb::TypeCategoryImplSP default_sp = lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs));
33    Add(default_cs,default_sp);
34    Enable(default_cs,First);
35}
36
37void
38TypeCategoryMap::Add (KeyType name, const ValueSP& entry)
39{
40    Mutex::Locker locker(m_map_mutex);
41    m_map[name] = entry;
42    if (listener)
43        listener->Changed();
44}
45
46bool
47TypeCategoryMap::Delete (KeyType name)
48{
49    Mutex::Locker locker(m_map_mutex);
50    MapIterator iter = m_map.find(name);
51    if (iter == m_map.end())
52        return false;
53    m_map.erase(name);
54    Disable(name);
55    if (listener)
56        listener->Changed();
57    return true;
58}
59
60bool
61TypeCategoryMap::Enable (KeyType category_name, Position pos)
62{
63    Mutex::Locker locker(m_map_mutex);
64    ValueSP category;
65    if (!Get(category_name,category))
66        return false;
67    return Enable(category, pos);
68}
69
70bool
71TypeCategoryMap::Disable (KeyType category_name)
72{
73    Mutex::Locker locker(m_map_mutex);
74    ValueSP category;
75    if (!Get(category_name,category))
76        return false;
77    return Disable(category);
78}
79
80bool
81TypeCategoryMap::Enable (ValueSP category, Position pos)
82{
83    Mutex::Locker locker(m_map_mutex);
84    if (category.get())
85    {
86        Position pos_w = pos;
87        if (pos == First || m_active_categories.size() == 0)
88            m_active_categories.push_front(category);
89        else if (pos == Last || pos == m_active_categories.size())
90            m_active_categories.push_back(category);
91        else if (pos < m_active_categories.size())
92        {
93            ActiveCategoriesList::iterator iter = m_active_categories.begin();
94            while (pos_w)
95            {
96                pos_w--,iter++;
97            }
98            m_active_categories.insert(iter,category);
99        }
100        else
101            return false;
102        category->Enable(true,
103                         pos);
104        return true;
105    }
106    return false;
107}
108
109bool
110TypeCategoryMap::Disable (ValueSP category)
111{
112    Mutex::Locker locker(m_map_mutex);
113    if (category.get())
114    {
115        m_active_categories.remove_if(delete_matching_categories(category));
116        category->Disable();
117        return true;
118    }
119    return false;
120}
121
122void
123TypeCategoryMap::Clear ()
124{
125    Mutex::Locker locker(m_map_mutex);
126    m_map.clear();
127    m_active_categories.clear();
128    if (listener)
129        listener->Changed();
130}
131
132bool
133TypeCategoryMap::Get (KeyType name, ValueSP& entry)
134{
135    Mutex::Locker locker(m_map_mutex);
136    MapIterator iter = m_map.find(name);
137    if (iter == m_map.end())
138        return false;
139    entry = iter->second;
140    return true;
141}
142
143bool
144TypeCategoryMap::Get (uint32_t pos, ValueSP& entry)
145{
146    Mutex::Locker locker(m_map_mutex);
147    MapIterator iter = m_map.begin();
148    MapIterator end = m_map.end();
149    while (pos > 0)
150    {
151        iter++;
152        pos--;
153        if (iter == end)
154            return false;
155    }
156    entry = iter->second;
157    return false;
158}
159
160bool
161TypeCategoryMap::AnyMatches (ConstString type_name,
162                             TypeCategoryImpl::FormatCategoryItems items,
163                             bool only_enabled,
164                             const char** matching_category,
165                             TypeCategoryImpl::FormatCategoryItems* matching_type)
166{
167    Mutex::Locker locker(m_map_mutex);
168
169    MapIterator pos, end = m_map.end();
170    for (pos = m_map.begin(); pos != end; pos++)
171    {
172        if (pos->second->AnyMatches(type_name,
173                                    items,
174                                    only_enabled,
175                                    matching_category,
176                                    matching_type))
177            return true;
178    }
179    return false;
180}
181
182lldb::TypeFormatImplSP
183TypeCategoryMap::GetFormat (ValueObject& valobj,
184                            lldb::DynamicValueType use_dynamic)
185{
186    Mutex::Locker locker(m_map_mutex);
187
188    uint32_t reason_why;
189    ActiveCategoriesIterator begin, end = m_active_categories.end();
190
191    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
192
193    FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
194
195    for (begin = m_active_categories.begin(); begin != end; begin++)
196    {
197        lldb::TypeCategoryImplSP category_sp = *begin;
198        lldb::TypeFormatImplSP current_format;
199        if (log)
200            log->Printf("\n[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName());
201        if (!category_sp->Get(valobj, matches, current_format, &reason_why))
202            continue;
203        return current_format;
204    }
205    if (log)
206        log->Printf("[TypeCategoryMap::GetFormat] nothing found - returning empty SP");
207    return lldb::TypeFormatImplSP();
208}
209
210lldb::TypeSummaryImplSP
211TypeCategoryMap::GetSummaryFormat (ValueObject& valobj,
212                                   lldb::DynamicValueType use_dynamic)
213{
214    Mutex::Locker locker(m_map_mutex);
215
216    uint32_t reason_why;
217    ActiveCategoriesIterator begin, end = m_active_categories.end();
218
219    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
220
221    FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
222
223    for (begin = m_active_categories.begin(); begin != end; begin++)
224    {
225        lldb::TypeCategoryImplSP category_sp = *begin;
226        lldb::TypeSummaryImplSP current_format;
227        if (log)
228            log->Printf("\n[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName());
229        if (!category_sp->Get(valobj, matches, current_format, &reason_why))
230            continue;
231        return current_format;
232    }
233    if (log)
234        log->Printf("[CategoryMap::GetSummaryFormat] nothing found - returning empty SP");
235    return lldb::TypeSummaryImplSP();
236}
237
238#ifndef LLDB_DISABLE_PYTHON
239lldb::SyntheticChildrenSP
240TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
241                                       lldb::DynamicValueType use_dynamic)
242{
243    Mutex::Locker locker(m_map_mutex);
244
245    uint32_t reason_why;
246
247    ActiveCategoriesIterator begin, end = m_active_categories.end();
248
249    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
250
251    FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
252
253    for (begin = m_active_categories.begin(); begin != end; begin++)
254    {
255        lldb::TypeCategoryImplSP category_sp = *begin;
256        lldb::SyntheticChildrenSP current_format;
257        if (log)
258            log->Printf("\n[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName());
259        if (!category_sp->Get(valobj, matches, current_format, &reason_why))
260            continue;
261        return current_format;
262    }
263    if (log)
264        log->Printf("[CategoryMap::GetSyntheticChildren] nothing found - returning empty SP");
265    return lldb::SyntheticChildrenSP();
266}
267#endif
268
269void
270TypeCategoryMap::LoopThrough(CallbackType callback, void* param)
271{
272    if (callback)
273    {
274        Mutex::Locker locker(m_map_mutex);
275
276        // loop through enabled categories in respective order
277        {
278            ActiveCategoriesIterator begin, end = m_active_categories.end();
279            for (begin = m_active_categories.begin(); begin != end; begin++)
280            {
281                lldb::TypeCategoryImplSP category = *begin;
282                ConstString type = ConstString(category->GetName());
283                if (!callback(param, category))
284                    break;
285            }
286        }
287
288        // loop through disabled categories in just any order
289        {
290            MapIterator pos, end = m_map.end();
291            for (pos = m_map.begin(); pos != end; pos++)
292            {
293                if (pos->second->IsEnabled())
294                    continue;
295                KeyType type = pos->first;
296                if (!callback(param, pos->second))
297                    break;
298            }
299        }
300    }
301}
302
303TypeCategoryImplSP
304TypeCategoryMap::GetAtIndex (uint32_t index)
305{
306    Mutex::Locker locker(m_map_mutex);
307
308    if (index < m_map.size())
309    {
310        MapIterator pos, end = m_map.end();
311        for (pos = m_map.begin(); pos != end; pos++)
312        {
313            if (index == 0)
314                return pos->second;
315            index--;
316        }
317    }
318
319    return TypeCategoryImplSP();
320}
321