TypeCategoryMap.cpp revision 280031
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::EnableAllCategories ()
124{
125    Mutex::Locker locker(m_map_mutex);
126    std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP());
127    MapType::iterator iter = m_map.begin(), end = m_map.end();
128    for (; iter != end; ++iter)
129    {
130        if (iter->second->IsEnabled())
131            continue;
132        auto pos = iter->second->GetLastEnabledPosition();
133        if (pos >= sorted_categories.size())
134        {
135            auto iter = std::find_if(sorted_categories.begin(),
136                                     sorted_categories.end(),
137                                     [] (const ValueSP& sp) -> bool {
138                                         return sp.get() == nullptr;
139                                     });
140            pos = std::distance(sorted_categories.begin(), iter);
141        }
142        sorted_categories.at(pos) = iter->second;
143    }
144    decltype(sorted_categories)::iterator viter = sorted_categories.begin(), vend = sorted_categories.end();
145    for (; viter != vend; viter++)
146        if (viter->get())
147            Enable(*viter, Last);
148}
149
150void
151TypeCategoryMap::DisableAllCategories ()
152{
153    Mutex::Locker locker(m_map_mutex);
154    Position p = First;
155    for (; false == m_active_categories.empty(); p++)
156    {
157        m_active_categories.front()->SetEnabledPosition(p);
158        Disable(m_active_categories.front());
159    }
160}
161
162void
163TypeCategoryMap::Clear ()
164{
165    Mutex::Locker locker(m_map_mutex);
166    m_map.clear();
167    m_active_categories.clear();
168    if (listener)
169        listener->Changed();
170}
171
172bool
173TypeCategoryMap::Get (KeyType name, ValueSP& entry)
174{
175    Mutex::Locker locker(m_map_mutex);
176    MapIterator iter = m_map.find(name);
177    if (iter == m_map.end())
178        return false;
179    entry = iter->second;
180    return true;
181}
182
183bool
184TypeCategoryMap::Get (uint32_t pos, ValueSP& entry)
185{
186    Mutex::Locker locker(m_map_mutex);
187    MapIterator iter = m_map.begin();
188    MapIterator end = m_map.end();
189    while (pos > 0)
190    {
191        iter++;
192        pos--;
193        if (iter == end)
194            return false;
195    }
196    entry = iter->second;
197    return false;
198}
199
200bool
201TypeCategoryMap::AnyMatches (ConstString type_name,
202                             TypeCategoryImpl::FormatCategoryItems items,
203                             bool only_enabled,
204                             const char** matching_category,
205                             TypeCategoryImpl::FormatCategoryItems* matching_type)
206{
207    Mutex::Locker locker(m_map_mutex);
208
209    MapIterator pos, end = m_map.end();
210    for (pos = m_map.begin(); pos != end; pos++)
211    {
212        if (pos->second->AnyMatches(type_name,
213                                    items,
214                                    only_enabled,
215                                    matching_category,
216                                    matching_type))
217            return true;
218    }
219    return false;
220}
221
222lldb::TypeFormatImplSP
223TypeCategoryMap::GetFormat (ValueObject& valobj,
224                            lldb::DynamicValueType use_dynamic)
225{
226    Mutex::Locker locker(m_map_mutex);
227
228    uint32_t reason_why;
229    ActiveCategoriesIterator begin, end = m_active_categories.end();
230
231    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
232
233    FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
234
235    for (begin = m_active_categories.begin(); begin != end; begin++)
236    {
237        lldb::TypeCategoryImplSP category_sp = *begin;
238        lldb::TypeFormatImplSP current_format;
239        if (log)
240            log->Printf("\n[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName());
241        if (!category_sp->Get(valobj, matches, current_format, &reason_why))
242            continue;
243        return current_format;
244    }
245    if (log)
246        log->Printf("[TypeCategoryMap::GetFormat] nothing found - returning empty SP");
247    return lldb::TypeFormatImplSP();
248}
249
250lldb::TypeSummaryImplSP
251TypeCategoryMap::GetSummaryFormat (ValueObject& valobj,
252                                   lldb::DynamicValueType use_dynamic)
253{
254    Mutex::Locker locker(m_map_mutex);
255
256    uint32_t reason_why;
257    ActiveCategoriesIterator begin, end = m_active_categories.end();
258
259    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
260
261    FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
262
263    for (begin = m_active_categories.begin(); begin != end; begin++)
264    {
265        lldb::TypeCategoryImplSP category_sp = *begin;
266        lldb::TypeSummaryImplSP current_format;
267        if (log)
268            log->Printf("\n[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName());
269        if (!category_sp->Get(valobj, matches, current_format, &reason_why))
270            continue;
271        return current_format;
272    }
273    if (log)
274        log->Printf("[CategoryMap::GetSummaryFormat] nothing found - returning empty SP");
275    return lldb::TypeSummaryImplSP();
276}
277
278#ifndef LLDB_DISABLE_PYTHON
279lldb::SyntheticChildrenSP
280TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
281                                       lldb::DynamicValueType use_dynamic)
282{
283    Mutex::Locker locker(m_map_mutex);
284
285    uint32_t reason_why;
286
287    ActiveCategoriesIterator begin, end = m_active_categories.end();
288
289    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
290
291    FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
292
293    for (begin = m_active_categories.begin(); begin != end; begin++)
294    {
295        lldb::TypeCategoryImplSP category_sp = *begin;
296        lldb::SyntheticChildrenSP current_format;
297        if (log)
298            log->Printf("\n[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName());
299        if (!category_sp->Get(valobj, matches, current_format, &reason_why))
300            continue;
301        return current_format;
302    }
303    if (log)
304        log->Printf("[CategoryMap::GetSyntheticChildren] nothing found - returning empty SP");
305    return lldb::SyntheticChildrenSP();
306}
307#endif
308
309lldb::TypeValidatorImplSP
310TypeCategoryMap::GetValidator (ValueObject& valobj,
311                               lldb::DynamicValueType use_dynamic)
312{
313    Mutex::Locker locker(m_map_mutex);
314
315    uint32_t reason_why;
316    ActiveCategoriesIterator begin, end = m_active_categories.end();
317
318    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
319
320    FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
321
322    for (begin = m_active_categories.begin(); begin != end; begin++)
323    {
324        lldb::TypeCategoryImplSP category_sp = *begin;
325        lldb::TypeValidatorImplSP current_format;
326        if (log)
327            log->Printf("\n[CategoryMap::GetValidator] Trying to use category %s", category_sp->GetName());
328        if (!category_sp->Get(valobj, matches, current_format, &reason_why))
329            continue;
330        return current_format;
331    }
332    if (log)
333        log->Printf("[CategoryMap::GetValidator] nothing found - returning empty SP");
334    return lldb::TypeValidatorImplSP();
335}
336
337void
338TypeCategoryMap::LoopThrough(CallbackType callback, void* param)
339{
340    if (callback)
341    {
342        Mutex::Locker locker(m_map_mutex);
343
344        // loop through enabled categories in respective order
345        {
346            ActiveCategoriesIterator begin, end = m_active_categories.end();
347            for (begin = m_active_categories.begin(); begin != end; begin++)
348            {
349                lldb::TypeCategoryImplSP category = *begin;
350                ConstString type = ConstString(category->GetName());
351                if (!callback(param, category))
352                    break;
353            }
354        }
355
356        // loop through disabled categories in just any order
357        {
358            MapIterator pos, end = m_map.end();
359            for (pos = m_map.begin(); pos != end; pos++)
360            {
361                if (pos->second->IsEnabled())
362                    continue;
363                KeyType type = pos->first;
364                if (!callback(param, pos->second))
365                    break;
366            }
367        }
368    }
369}
370
371TypeCategoryImplSP
372TypeCategoryMap::GetAtIndex (uint32_t index)
373{
374    Mutex::Locker locker(m_map_mutex);
375
376    if (index < m_map.size())
377    {
378        MapIterator pos, end = m_map.end();
379        for (pos = m_map.begin(); pos != end; pos++)
380        {
381            if (index == 0)
382                return pos->second;
383            index--;
384        }
385    }
386
387    return TypeCategoryImplSP();
388}
389