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