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