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
150 SBTypeSummary::CreateWithCallback (FormatCallback cb, uint32_t options)
151 {
152     return SBTypeSummary(
153                TypeSummaryImplSP(
154                    cb ? new CXXFunctionSummaryFormat(options,
155                        [cb] (ValueObject& valobj, Stream& stm, const TypeSummaryOptions& opt) -> bool {
156                             SBStream stream;
157                             if (!cb(SBValue(valobj.GetSP()), SBTypeSummaryOptions(&opt), stream))
158                                 return false;
159                             stm.Write(stream.GetData(), stream.GetSize());
160                             return true;
161                        },
162                        "SBTypeSummary formatter callback"
163                    ) : nullptr
164                 )
165             );
166 }
167 
168 SBTypeSummary::SBTypeSummary (const lldb::SBTypeSummary &rhs) :
169 m_opaque_sp(rhs.m_opaque_sp)
170 {
171 }
172 
173 SBTypeSummary::~SBTypeSummary ()
174 {
175 }
176 
177 bool
178 SBTypeSummary::IsValid() const
179 {
180     return m_opaque_sp.get() != NULL;
181 }
182 
183 bool
184 SBTypeSummary::IsFunctionCode()
185 {
186     if (!IsValid())
187         return false;
188     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
189     {
190         const char* ftext = script_summary_ptr->GetPythonScript();
191         return (ftext && *ftext != 0);
192     }
193     return false;
194 }
195 
196 bool
197 SBTypeSummary::IsFunctionName()
198 {
199     if (!IsValid())
200         return false;
201     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
202     {
203         const char* ftext = script_summary_ptr->GetPythonScript();
204         return (!ftext || *ftext == 0);
205     }
206     return false;
207 }
208 
209 bool
210 SBTypeSummary::IsSummaryString()
211 {
212     if (!IsValid())
213         return false;
214 
215     return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString;
216 }
217 
218 const char*
219 SBTypeSummary::GetData ()
220 {
221     if (!IsValid())
222         return NULL;
223     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
224     {
225         const char* fname = script_summary_ptr->GetFunctionName();
226         const char* ftext = script_summary_ptr->GetPythonScript();
227         if (ftext && *ftext)
228             return ftext;
229         return fname;
230     }
231     else if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
232         return string_summary_ptr->GetSummaryString();
233     return nullptr;
234 }
235 
236 uint32_t
237 SBTypeSummary::GetOptions ()
238 {
239     if (!IsValid())
240         return lldb::eTypeOptionNone;
241     return m_opaque_sp->GetOptions();
242 }
243 
244 void
245 SBTypeSummary::SetOptions (uint32_t value)
246 {
247     if (!CopyOnWrite_Impl())
248         return;
249     m_opaque_sp->SetOptions(value);
250 }
251 
252 void
253 SBTypeSummary::SetSummaryString (const char* data)
254 {
255     if (!IsValid())
256         return;
257     if (!llvm::isa<StringSummaryFormat>(m_opaque_sp.get()))
258         ChangeSummaryType(false);
259     if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
260         string_summary_ptr->SetSummaryString(data);
261 }
262 
263 void
264 SBTypeSummary::SetFunctionName (const char* data)
265 {
266     if (!IsValid())
267         return;
268     if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
269         ChangeSummaryType(true);
270     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
271         script_summary_ptr->SetFunctionName(data);
272 }
273 
274 void
275 SBTypeSummary::SetFunctionCode (const char* data)
276 {
277     if (!IsValid())
278         return;
279     if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
280         ChangeSummaryType(true);
281     if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
282         script_summary_ptr->SetPythonScript(data);
283 }
284 
285 bool
286 SBTypeSummary::GetDescription (lldb::SBStream &description,
287                               lldb::DescriptionLevel description_level)
288 {
289     if (!CopyOnWrite_Impl())
290         return false;
291     else {
292         description.Printf("%s\n",
293                            m_opaque_sp->GetDescription().c_str());
294         return true;
295     }
296 }
297 
298 bool
299 SBTypeSummary::DoesPrintValue (lldb::SBValue value)
300 {
301     if (!IsValid())
302         return false;
303     lldb::ValueObjectSP value_sp = value.GetSP();
304     return m_opaque_sp->DoesPrintValue(value_sp.get());
305 }
306 
307 lldb::SBTypeSummary &
308 SBTypeSummary::operator = (const lldb::SBTypeSummary &rhs)
309 {
310     if (this != &rhs)
311     {
312         m_opaque_sp = rhs.m_opaque_sp;
313     }
314     return *this;
315 }
316 
317 bool
318 SBTypeSummary::operator == (lldb::SBTypeSummary &rhs)
319 {
320     if (IsValid() == false)
321         return !rhs.IsValid();
322     return m_opaque_sp == rhs.m_opaque_sp;
323 }
324 
325 bool
326 SBTypeSummary::IsEqualTo (lldb::SBTypeSummary &rhs)
327 {
328     if (IsValid() == false)
329         return !rhs.IsValid();
330 
331     if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind())
332         return false;
333 
334     switch (m_opaque_sp->GetKind())
335     {
336         case TypeSummaryImpl::Kind::eCallback:
337             return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) == llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get());
338         case TypeSummaryImpl::Kind::eScript:
339             if (IsFunctionCode() != rhs.IsFunctionCode())
340                 return false;
341             if (IsFunctionName() != rhs.IsFunctionName())
342                 return false;
343             return GetOptions() == rhs.GetOptions();
344         case TypeSummaryImpl::Kind::eSummaryString:
345             if (IsSummaryString() != rhs.IsSummaryString())
346                 return false;
347             return GetOptions() == rhs.GetOptions();
348     }
349 
350     return false;
351 }
352 
353 bool
354 SBTypeSummary::operator != (lldb::SBTypeSummary &rhs)
355 {
356     if (IsValid() == false)
357         return !rhs.IsValid();
358     return m_opaque_sp != rhs.m_opaque_sp;
359 }
360 
361 lldb::TypeSummaryImplSP
362 SBTypeSummary::GetSP ()
363 {
364     return m_opaque_sp;
365 }
366 
367 void
368 SBTypeSummary::SetSP (const lldb::TypeSummaryImplSP &typesummary_impl_sp)
369 {
370     m_opaque_sp = typesummary_impl_sp;
371 }
372 
373 SBTypeSummary::SBTypeSummary (const lldb::TypeSummaryImplSP &typesummary_impl_sp) :
374 m_opaque_sp(typesummary_impl_sp)
375 {
376 }
377 
378 bool
379 SBTypeSummary::CopyOnWrite_Impl()
380 {
381     if (!IsValid())
382         return false;
383 
384     if (m_opaque_sp.unique())
385         return true;
386 
387     TypeSummaryImplSP new_sp;
388 
389     if (CXXFunctionSummaryFormat* current_summary_ptr = llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()))
390     {
391         new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(GetOptions(),
392                                                                 current_summary_ptr->m_impl,
393                                                                 current_summary_ptr->m_description.c_str()));
394     }
395     else if (ScriptSummaryFormat* current_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
396     {
397         new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(),
398                                                            current_summary_ptr->GetFunctionName(),
399                                                            current_summary_ptr->GetPythonScript()));
400     }
401     else if (StringSummaryFormat* current_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
402     {
403         new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(),
404                                                            current_summary_ptr->GetSummaryString()));
405     }
406 
407     SetSP(new_sp);
408 
409     return nullptr != new_sp.get();
410 }
411 
412 bool
413 SBTypeSummary::ChangeSummaryType (bool want_script)
414 {
415     if (!IsValid())
416         return false;
417 
418     TypeSummaryImplSP new_sp;
419 
420     if (want_script == (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript))
421     {
422         if (m_opaque_sp->GetKind() == lldb_private::TypeSummaryImpl::Kind::eCallback && !want_script)
423             new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
424         else
425             return CopyOnWrite_Impl();
426     }
427 
428     if (!new_sp)
429     {
430         if (want_script)
431             new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", ""));
432         else
433             new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
434     }
435 
436     SetSP(new_sp);
437 
438     return true;
439 }
440