1 //===-- SBTypeSummary.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/API/SBTypeSummary.h"
11 #include "lldb/API/SBStream.h"
12 #include "lldb/API/SBValue.h"
13 #include "lldb/DataFormatters/DataVisualization.h"
14 
15 #include "llvm/Support/Casting.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 SBTypeSummaryOptions::SBTypeSummaryOptions()
21 {
22     m_opaque_ap.reset(new TypeSummaryOptions());
23 }
24 
25 SBTypeSummaryOptions::SBTypeSummaryOptions (const lldb::SBTypeSummaryOptions &rhs)
26 {
27     if (rhs.m_opaque_ap)
28         m_opaque_ap.reset(new TypeSummaryOptions(*rhs.m_opaque_ap.get()));
29     else
30         m_opaque_ap.reset(new TypeSummaryOptions());
31 }
32 
33 SBTypeSummaryOptions::~SBTypeSummaryOptions ()
34 {
35 }
36 
37 bool
38 SBTypeSummaryOptions::IsValid()
39 {
40     return m_opaque_ap.get();
41 }
42 
43 lldb::LanguageType
44 SBTypeSummaryOptions::GetLanguage ()
45 {
46     if (IsValid())
47         return m_opaque_ap->GetLanguage();
48     return lldb::eLanguageTypeUnknown;
49 }
50 
51 lldb::TypeSummaryCapping
52 SBTypeSummaryOptions::GetCapping ()
53 {
54     if (IsValid())
55         return m_opaque_ap->GetCapping();
56     return eTypeSummaryCapped;
57 }
58 
59 void
60 SBTypeSummaryOptions::SetLanguage (lldb::LanguageType l)
61 {
62     if (IsValid())
63         m_opaque_ap->SetLanguage(l);
64 }
65 
66 void
67 SBTypeSummaryOptions::SetCapping (lldb::TypeSummaryCapping c)
68 {
69     if (IsValid())
70         m_opaque_ap->SetCapping(c);
71 }
72 
73 lldb_private::TypeSummaryOptions *
74 SBTypeSummaryOptions::operator->()
75 {
76     return m_opaque_ap.get();
77 }
78 
79 const lldb_private::TypeSummaryOptions *
80 SBTypeSummaryOptions::operator->() const
81 {
82     return m_opaque_ap.get();
83 }
84 
85 lldb_private::TypeSummaryOptions *
86 SBTypeSummaryOptions::get ()
87 {
88     return m_opaque_ap.get();
89 }
90 
91 lldb_private::TypeSummaryOptions &
92 SBTypeSummaryOptions::ref()
93 {
94     return *m_opaque_ap.get();
95 }
96 
97 const lldb_private::TypeSummaryOptions &
98 SBTypeSummaryOptions::ref() const
99 {
100     return *m_opaque_ap.get();
101 }
102 
103 SBTypeSummaryOptions::SBTypeSummaryOptions (const lldb_private::TypeSummaryOptions *lldb_object_ptr)
104 {
105     SetOptions(lldb_object_ptr);
106 }
107 
108 void
109 SBTypeSummaryOptions::SetOptions (const lldb_private::TypeSummaryOptions *lldb_object_ptr)
110 {
111     if (lldb_object_ptr)
112         m_opaque_ap.reset(new TypeSummaryOptions(*lldb_object_ptr));
113     else
114         m_opaque_ap.reset(new TypeSummaryOptions());
115 }
116 
117 SBTypeSummary::SBTypeSummary() :
118 m_opaque_sp()
119 {
120 }
121 
122 SBTypeSummary
123 SBTypeSummary::CreateWithSummaryString (const char* data, uint32_t options)
124 {
125     if (!data || data[0] == 0)
126         return SBTypeSummary();
127 
128     return SBTypeSummary(TypeSummaryImplSP(new StringSummaryFormat(options, data)));
129 }
130 
131 SBTypeSummary
132 SBTypeSummary::CreateWithFunctionName (const char* data, uint32_t options)
133 {
134     if (!data || data[0] == 0)
135         return SBTypeSummary();
136 
137     return SBTypeSummary(TypeSummaryImplSP(new ScriptSummaryFormat(options, data)));
138 }
139 
140 SBTypeSummary
141 SBTypeSummary::CreateWithScriptCode (const char* data, uint32_t options)
142 {
143     if (!data || data[0] == 0)
144         return SBTypeSummary();
145 
146     return SBTypeSummary(TypeSummaryImplSP(new ScriptSummaryFormat(options, "", data)));
147 }
148 
149 SBTypeSummary::SBTypeSummary (const lldb::SBTypeSummary &rhs) :
150 m_opaque_sp(rhs.m_opaque_sp)
151 {
152 }
153 
154 SBTypeSummary::~SBTypeSummary ()
155 {
156 }
157 
158 bool
159 SBTypeSummary::IsValid() const
160 {
161     return m_opaque_sp.get() != NULL;
162 }
163 
164 bool
165 SBTypeSummary::IsFunctionCode()
166 {
167     if (!IsValid())
168         return false;
169     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
170     {
171         const char* ftext = script_summary_ptr->GetPythonScript();
172         return (ftext && *ftext != 0);
173     }
174     return false;
175 }
176 
177 bool
178 SBTypeSummary::IsFunctionName()
179 {
180     if (!IsValid())
181         return false;
182     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
183     {
184         const char* ftext = script_summary_ptr->GetPythonScript();
185         return (!ftext || *ftext == 0);
186     }
187     return false;
188 }
189 
190 bool
191 SBTypeSummary::IsSummaryString()
192 {
193     if (!IsValid())
194         return false;
195 
196     return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString;
197 }
198 
199 const char*
200 SBTypeSummary::GetData ()
201 {
202     if (!IsValid())
203         return NULL;
204     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
205     {
206         const char* fname = script_summary_ptr->GetFunctionName();
207         const char* ftext = script_summary_ptr->GetPythonScript();
208         if (ftext && *ftext)
209             return ftext;
210         return fname;
211     }
212     else if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
213         return string_summary_ptr->GetSummaryString();
214     return nullptr;
215 }
216 
217 uint32_t
218 SBTypeSummary::GetOptions ()
219 {
220     if (!IsValid())
221         return lldb::eTypeOptionNone;
222     return m_opaque_sp->GetOptions();
223 }
224 
225 void
226 SBTypeSummary::SetOptions (uint32_t value)
227 {
228     if (!CopyOnWrite_Impl())
229         return;
230     m_opaque_sp->SetOptions(value);
231 }
232 
233 void
234 SBTypeSummary::SetSummaryString (const char* data)
235 {
236     if (!IsValid())
237         return;
238     if (!llvm::isa<StringSummaryFormat>(m_opaque_sp.get()))
239         ChangeSummaryType(false);
240     if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
241         string_summary_ptr->SetSummaryString(data);
242 }
243 
244 void
245 SBTypeSummary::SetFunctionName (const char* data)
246 {
247     if (!IsValid())
248         return;
249     if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
250         ChangeSummaryType(true);
251     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
252         script_summary_ptr->SetFunctionName(data);
253 }
254 
255 void
256 SBTypeSummary::SetFunctionCode (const char* data)
257 {
258     if (!IsValid())
259         return;
260     if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
261         ChangeSummaryType(true);
262     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
263         script_summary_ptr->SetPythonScript(data);
264 }
265 
266 bool
267 SBTypeSummary::GetDescription (lldb::SBStream &description,
268                               lldb::DescriptionLevel description_level)
269 {
270     if (!CopyOnWrite_Impl())
271         return false;
272     else {
273         description.Printf("%s\n",
274                            m_opaque_sp->GetDescription().c_str());
275         return true;
276     }
277 }
278 
279 bool
280 SBTypeSummary::DoesPrintValue (lldb::SBValue value)
281 {
282     if (!IsValid())
283         return false;
284     lldb::ValueObjectSP value_sp = value.GetSP();
285     return m_opaque_sp->DoesPrintValue(value_sp.get());
286 }
287 
288 lldb::SBTypeSummary &
289 SBTypeSummary::operator = (const lldb::SBTypeSummary &rhs)
290 {
291     if (this != &rhs)
292     {
293         m_opaque_sp = rhs.m_opaque_sp;
294     }
295     return *this;
296 }
297 
298 bool
299 SBTypeSummary::operator == (lldb::SBTypeSummary &rhs)
300 {
301     if (IsValid() == false)
302         return !rhs.IsValid();
303     return m_opaque_sp == rhs.m_opaque_sp;
304 }
305 
306 bool
307 SBTypeSummary::IsEqualTo (lldb::SBTypeSummary &rhs)
308 {
309     if (IsValid() == false)
310         return !rhs.IsValid();
311 
312     if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind())
313         return false;
314 
315     switch (m_opaque_sp->GetKind())
316     {
317         case TypeSummaryImpl::Kind::eCallback:
318             return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) == llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get());
319         case TypeSummaryImpl::Kind::eScript:
320             if (IsFunctionCode() != rhs.IsFunctionCode())
321                 return false;
322             if (IsFunctionName() != rhs.IsFunctionName())
323                 return false;
324             return GetOptions() == rhs.GetOptions();
325         case TypeSummaryImpl::Kind::eSummaryString:
326             if (IsSummaryString() != rhs.IsSummaryString())
327                 return false;
328             return GetOptions() == rhs.GetOptions();
329     }
330 
331     return false;
332 }
333 
334 bool
335 SBTypeSummary::operator != (lldb::SBTypeSummary &rhs)
336 {
337     if (IsValid() == false)
338         return !rhs.IsValid();
339     return m_opaque_sp != rhs.m_opaque_sp;
340 }
341 
342 lldb::TypeSummaryImplSP
343 SBTypeSummary::GetSP ()
344 {
345     return m_opaque_sp;
346 }
347 
348 void
349 SBTypeSummary::SetSP (const lldb::TypeSummaryImplSP &typesummary_impl_sp)
350 {
351     m_opaque_sp = typesummary_impl_sp;
352 }
353 
354 SBTypeSummary::SBTypeSummary (const lldb::TypeSummaryImplSP &typesummary_impl_sp) :
355 m_opaque_sp(typesummary_impl_sp)
356 {
357 }
358 
359 bool
360 SBTypeSummary::CopyOnWrite_Impl()
361 {
362     if (!IsValid())
363         return false;
364 
365     if (m_opaque_sp.unique())
366         return true;
367 
368     TypeSummaryImplSP new_sp;
369 
370     if (CXXFunctionSummaryFormat* current_summary_ptr = llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()))
371     {
372         new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(GetOptions(),
373                                                                 current_summary_ptr->m_impl,
374                                                                 current_summary_ptr->m_description.c_str()));
375     }
376     else if (ScriptSummaryFormat* current_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
377     {
378         new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(),
379                                                            current_summary_ptr->GetFunctionName(),
380                                                            current_summary_ptr->GetPythonScript()));
381     }
382     else if (StringSummaryFormat* current_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
383     {
384         new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(),
385                                                            current_summary_ptr->GetSummaryString()));
386     }
387 
388     SetSP(new_sp);
389 
390     return nullptr != new_sp.get();
391 }
392 
393 bool
394 SBTypeSummary::ChangeSummaryType (bool want_script)
395 {
396     if (!IsValid())
397         return false;
398 
399     TypeSummaryImplSP new_sp;
400 
401     if (want_script == (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript))
402     {
403         if (m_opaque_sp->GetKind() == lldb_private::TypeSummaryImpl::Kind::eCallback && !want_script)
404             new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
405         else
406             return CopyOnWrite_Impl();
407     }
408 
409     if (!new_sp)
410     {
411         if (want_script)
412             new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", ""));
413         else
414             new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
415     }
416 
417     SetSP(new_sp);
418 
419     return true;
420 }
421