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