1//===-- TypeCategory.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/TypeCategory.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18
19using namespace lldb;
20using namespace lldb_private;
21
22TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener* clist,
23                                   ConstString name) :
24m_summary_nav(new SummaryNavigator("summary",clist)),
25m_regex_summary_nav(new RegexSummaryNavigator("regex-summary",clist)),
26m_filter_nav(new FilterNavigator("filter",clist)),
27m_regex_filter_nav(new RegexFilterNavigator("regex-filter",clist)),
28#ifndef LLDB_DISABLE_PYTHON
29m_synth_nav(new SynthNavigator("synth",clist)),
30m_regex_synth_nav(new RegexSynthNavigator("regex-synth",clist)),
31#endif
32m_enabled(false),
33m_change_listener(clist),
34m_mutex(Mutex::eMutexTypeRecursive),
35m_name(name)
36{}
37
38bool
39TypeCategoryImpl::Get (ValueObject& valobj,
40                       lldb::TypeSummaryImplSP& entry,
41                       lldb::DynamicValueType use_dynamic,
42                       uint32_t* reason)
43{
44    if (!IsEnabled())
45        return false;
46    if (GetSummaryNavigator()->Get(valobj, entry, use_dynamic, reason))
47        return true;
48    bool regex = GetRegexSummaryNavigator()->Get(valobj, entry, use_dynamic, reason);
49    if (regex && reason)
50        *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
51    return regex;
52}
53
54bool
55TypeCategoryImpl::Get(ValueObject& valobj,
56                      lldb::SyntheticChildrenSP& entry_sp,
57                      lldb::DynamicValueType use_dynamic,
58                      uint32_t* reason)
59{
60    if (!IsEnabled())
61        return false;
62    TypeFilterImpl::SharedPointer filter_sp;
63    uint32_t reason_filter = 0;
64    bool regex_filter = false;
65    // first find both Filter and Synth, and then check which is most recent
66
67    if (!GetFilterNavigator()->Get(valobj, filter_sp, use_dynamic, &reason_filter))
68        regex_filter = GetRegexFilterNavigator()->Get (valobj, filter_sp, use_dynamic, &reason_filter);
69
70#ifndef LLDB_DISABLE_PYTHON
71    bool regex_synth = false;
72    uint32_t reason_synth = 0;
73    bool pick_synth = false;
74    ScriptedSyntheticChildren::SharedPointer synth;
75    if (!GetSyntheticNavigator()->Get(valobj, synth, use_dynamic, &reason_synth))
76        regex_synth = GetRegexSyntheticNavigator()->Get (valobj, synth, use_dynamic, &reason_synth);
77    if (!filter_sp.get() && !synth.get())
78        return false;
79    else if (!filter_sp.get() && synth.get())
80        pick_synth = true;
81
82    else if (filter_sp.get() && !synth.get())
83        pick_synth = false;
84
85    else /*if (filter_sp.get() && synth.get())*/
86    {
87        if (filter_sp->GetRevision() > synth->GetRevision())
88            pick_synth = false;
89        else
90            pick_synth = true;
91    }
92    if (pick_synth)
93    {
94        if (regex_synth && reason)
95            *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
96        entry_sp = synth;
97        return true;
98    }
99    else
100    {
101        if (regex_filter && reason)
102            *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
103        entry_sp = filter_sp;
104        return true;
105    }
106
107#else
108    if (filter_sp)
109    {
110        entry_sp = filter_sp;
111        return true;
112    }
113#endif
114
115    return false;
116
117}
118
119void
120TypeCategoryImpl::Clear (FormatCategoryItems items)
121{
122    if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
123        m_summary_nav->Clear();
124    if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
125        m_regex_summary_nav->Clear();
126    if ( (items & eFormatCategoryItemFilter)  == eFormatCategoryItemFilter )
127        m_filter_nav->Clear();
128    if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
129        m_regex_filter_nav->Clear();
130#ifndef LLDB_DISABLE_PYTHON
131    if ( (items & eFormatCategoryItemSynth)  == eFormatCategoryItemSynth )
132        m_synth_nav->Clear();
133    if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
134        m_regex_synth_nav->Clear();
135#endif
136}
137
138bool
139TypeCategoryImpl::Delete (ConstString name,
140                          FormatCategoryItems items)
141{
142    bool success = false;
143    if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
144        success = m_summary_nav->Delete(name) || success;
145    if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
146        success = m_regex_summary_nav->Delete(name) || success;
147    if ( (items & eFormatCategoryItemFilter)  == eFormatCategoryItemFilter )
148        success = m_filter_nav->Delete(name) || success;
149    if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
150        success = m_regex_filter_nav->Delete(name) || success;
151#ifndef LLDB_DISABLE_PYTHON
152    if ( (items & eFormatCategoryItemSynth)  == eFormatCategoryItemSynth )
153        success = m_synth_nav->Delete(name) || success;
154    if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
155        success = m_regex_synth_nav->Delete(name) || success;
156#endif
157    return success;
158}
159
160uint32_t
161TypeCategoryImpl::GetCount (FormatCategoryItems items)
162{
163    uint32_t count = 0;
164    if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
165        count += m_summary_nav->GetCount();
166    if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
167        count += m_regex_summary_nav->GetCount();
168    if ( (items & eFormatCategoryItemFilter)  == eFormatCategoryItemFilter )
169        count += m_filter_nav->GetCount();
170    if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
171        count += m_regex_filter_nav->GetCount();
172#ifndef LLDB_DISABLE_PYTHON
173    if ( (items & eFormatCategoryItemSynth)  == eFormatCategoryItemSynth )
174        count += m_synth_nav->GetCount();
175    if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
176        count += m_regex_synth_nav->GetCount();
177#endif
178    return count;
179}
180
181bool
182TypeCategoryImpl::AnyMatches(ConstString type_name,
183                             FormatCategoryItems items,
184                             bool only_enabled,
185                             const char** matching_category,
186                             FormatCategoryItems* matching_type)
187{
188    if (!IsEnabled() && only_enabled)
189        return false;
190
191    lldb::TypeSummaryImplSP summary;
192    TypeFilterImpl::SharedPointer filter;
193#ifndef LLDB_DISABLE_PYTHON
194    ScriptedSyntheticChildren::SharedPointer synth;
195#endif
196
197    if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
198    {
199        if (m_summary_nav->Get(type_name, summary))
200        {
201            if (matching_category)
202                *matching_category = m_name.GetCString();
203            if (matching_type)
204                *matching_type = eFormatCategoryItemSummary;
205            return true;
206        }
207    }
208    if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
209    {
210        if (m_regex_summary_nav->Get(type_name, summary))
211        {
212            if (matching_category)
213                *matching_category = m_name.GetCString();
214            if (matching_type)
215                *matching_type = eFormatCategoryItemRegexSummary;
216            return true;
217        }
218    }
219    if ( (items & eFormatCategoryItemFilter)  == eFormatCategoryItemFilter )
220    {
221        if (m_filter_nav->Get(type_name, filter))
222        {
223            if (matching_category)
224                *matching_category = m_name.GetCString();
225            if (matching_type)
226                *matching_type = eFormatCategoryItemFilter;
227            return true;
228        }
229    }
230    if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
231    {
232        if (m_regex_filter_nav->Get(type_name, filter))
233        {
234            if (matching_category)
235                *matching_category = m_name.GetCString();
236            if (matching_type)
237                *matching_type = eFormatCategoryItemRegexFilter;
238            return true;
239        }
240    }
241#ifndef LLDB_DISABLE_PYTHON
242    if ( (items & eFormatCategoryItemSynth)  == eFormatCategoryItemSynth )
243    {
244        if (m_synth_nav->Get(type_name, synth))
245        {
246            if (matching_category)
247                *matching_category = m_name.GetCString();
248            if (matching_type)
249                *matching_type = eFormatCategoryItemSynth;
250            return true;
251        }
252    }
253    if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
254    {
255        if (m_regex_synth_nav->Get(type_name, synth))
256        {
257            if (matching_category)
258                *matching_category = m_name.GetCString();
259            if (matching_type)
260                *matching_type = eFormatCategoryItemRegexSynth;
261            return true;
262        }
263    }
264#endif
265    return false;
266}
267
268TypeCategoryImpl::SummaryNavigator::MapValueType
269TypeCategoryImpl::GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp)
270{
271    SummaryNavigator::MapValueType retval;
272
273    if (type_sp)
274    {
275        if (type_sp->IsRegex())
276            m_regex_summary_nav->GetExact(ConstString(type_sp->GetName()),retval);
277        else
278            m_summary_nav->GetExact(ConstString(type_sp->GetName()),retval);
279    }
280
281    return retval;
282}
283
284TypeCategoryImpl::FilterNavigator::MapValueType
285TypeCategoryImpl::GetFilterForType (lldb::TypeNameSpecifierImplSP type_sp)
286{
287    FilterNavigator::MapValueType retval;
288
289    if (type_sp)
290    {
291        if (type_sp->IsRegex())
292            m_regex_filter_nav->GetExact(ConstString(type_sp->GetName()),retval);
293        else
294            m_filter_nav->GetExact(ConstString(type_sp->GetName()),retval);
295    }
296
297    return retval;
298}
299
300#ifndef LLDB_DISABLE_PYTHON
301TypeCategoryImpl::SynthNavigator::MapValueType
302TypeCategoryImpl::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp)
303{
304    SynthNavigator::MapValueType retval;
305
306    if (type_sp)
307    {
308        if (type_sp->IsRegex())
309            m_regex_synth_nav->GetExact(ConstString(type_sp->GetName()),retval);
310        else
311            m_synth_nav->GetExact(ConstString(type_sp->GetName()),retval);
312    }
313
314    return retval;
315}
316#endif
317
318lldb::TypeNameSpecifierImplSP
319TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex (size_t index)
320{
321    if (index < m_summary_nav->GetCount())
322        return m_summary_nav->GetTypeNameSpecifierAtIndex(index);
323    else
324        return m_regex_summary_nav->GetTypeNameSpecifierAtIndex(index-m_summary_nav->GetCount());
325}
326
327TypeCategoryImpl::SummaryNavigator::MapValueType
328TypeCategoryImpl::GetSummaryAtIndex (size_t index)
329{
330    if (index < m_summary_nav->GetCount())
331        return m_summary_nav->GetAtIndex(index);
332    else
333        return m_regex_summary_nav->GetAtIndex(index-m_summary_nav->GetCount());
334}
335
336TypeCategoryImpl::FilterNavigator::MapValueType
337TypeCategoryImpl::GetFilterAtIndex (size_t index)
338{
339    if (index < m_filter_nav->GetCount())
340        return m_filter_nav->GetAtIndex(index);
341    else
342        return m_regex_filter_nav->GetAtIndex(index-m_filter_nav->GetCount());
343}
344
345lldb::TypeNameSpecifierImplSP
346TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex (size_t index)
347{
348    if (index < m_filter_nav->GetCount())
349        return m_filter_nav->GetTypeNameSpecifierAtIndex(index);
350    else
351        return m_regex_filter_nav->GetTypeNameSpecifierAtIndex(index-m_filter_nav->GetCount());
352}
353
354#ifndef LLDB_DISABLE_PYTHON
355TypeCategoryImpl::SynthNavigator::MapValueType
356TypeCategoryImpl::GetSyntheticAtIndex (size_t index)
357{
358    if (index < m_synth_nav->GetCount())
359        return m_synth_nav->GetAtIndex(index);
360    else
361        return m_regex_synth_nav->GetAtIndex(index-m_synth_nav->GetCount());
362}
363
364lldb::TypeNameSpecifierImplSP
365TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex (size_t index)
366{
367    if (index < m_synth_nav->GetCount())
368        return m_synth_nav->GetTypeNameSpecifierAtIndex(index);
369    else
370        return m_regex_synth_nav->GetTypeNameSpecifierAtIndex(index - m_synth_nav->GetCount());
371}
372#endif
373
374void
375TypeCategoryImpl::Enable (bool value, uint32_t position)
376{
377    Mutex::Locker locker(m_mutex);
378    m_enabled = value;
379    m_enabled_position = position;
380    if (m_change_listener)
381        m_change_listener->Changed();
382}
383