TypeSynthetic.h revision f509c5ec066599a3399fced39ea36996184939e8
1//===-- TypeSynthetic.h -------------------------------------------*- 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#ifndef lldb_TypeSynthetic_h_ 11#define lldb_TypeSynthetic_h_ 12 13// C Includes 14#include <stdint.h> 15#include <unistd.h> 16 17// C++ Includes 18#include <string> 19#include <vector> 20 21// Other libraries and framework includes 22 23// Project includes 24#include "lldb/lldb-public.h" 25#include "lldb/lldb-enumerations.h" 26 27#include "lldb/Core/ValueObject.h" 28#include "lldb/Interpreter/ScriptInterpreterPython.h" 29#include "lldb/Symbol/Type.h" 30 31namespace lldb_private { 32 class SyntheticChildrenFrontEnd 33 { 34 protected: 35 ValueObject &m_backend; 36 public: 37 38 SyntheticChildrenFrontEnd (ValueObject &backend) : 39 m_backend(backend) 40 {} 41 42 virtual 43 ~SyntheticChildrenFrontEnd () 44 { 45 } 46 47 virtual size_t 48 CalculateNumChildren () = 0; 49 50 virtual lldb::ValueObjectSP 51 GetChildAtIndex (size_t idx) = 0; 52 53 virtual size_t 54 GetIndexOfChildWithName (const ConstString &name) = 0; 55 56 // this function is assumed to always succeed and it if fails, the front-end should know to deal 57 // with it in the correct way (most probably, by refusing to return any children) 58 // the return value of Update() should actually be interpreted as "ValueObjectSyntheticFilter cache is good/bad" 59 // if =true, ValueObjectSyntheticFilter is allowed to use the children it fetched previously and cached 60 // if =false, ValueObjectSyntheticFilter must throw away its cache, and query again for children 61 virtual bool 62 Update () = 0; 63 64 // if this function returns false, then CalculateNumChildren() MUST return 0 since UI frontends 65 // might validly decide not to inquire for children given a false return value from this call 66 // if it returns true, then CalculateNumChildren() can return any number >= 0 (0 being valid) 67 // it should if at all possible be more efficient than CalculateNumChildren() 68 virtual bool 69 MightHaveChildren () = 0; 70 71 typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; 72 typedef std::auto_ptr<SyntheticChildrenFrontEnd> AutoPointer; 73 74 private: 75 DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd); 76 }; 77 78 class SyntheticChildren 79 { 80 public: 81 82 class Flags 83 { 84 public: 85 86 Flags () : 87 m_flags (lldb::eTypeOptionCascade) 88 {} 89 90 Flags (const Flags& other) : 91 m_flags (other.m_flags) 92 {} 93 94 Flags (uint32_t value) : 95 m_flags (value) 96 {} 97 98 Flags& 99 operator = (const Flags& rhs) 100 { 101 if (&rhs != this) 102 m_flags = rhs.m_flags; 103 104 return *this; 105 } 106 107 Flags& 108 operator = (const uint32_t& rhs) 109 { 110 m_flags = rhs; 111 return *this; 112 } 113 114 Flags& 115 Clear() 116 { 117 m_flags = 0; 118 return *this; 119 } 120 121 bool 122 GetCascades () const 123 { 124 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; 125 } 126 127 Flags& 128 SetCascades (bool value = true) 129 { 130 if (value) 131 m_flags |= lldb::eTypeOptionCascade; 132 else 133 m_flags &= ~lldb::eTypeOptionCascade; 134 return *this; 135 } 136 137 bool 138 GetSkipPointers () const 139 { 140 return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; 141 } 142 143 Flags& 144 SetSkipPointers (bool value = true) 145 { 146 if (value) 147 m_flags |= lldb::eTypeOptionSkipPointers; 148 else 149 m_flags &= ~lldb::eTypeOptionSkipPointers; 150 return *this; 151 } 152 153 bool 154 GetSkipReferences () const 155 { 156 return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; 157 } 158 159 Flags& 160 SetSkipReferences (bool value = true) 161 { 162 if (value) 163 m_flags |= lldb::eTypeOptionSkipReferences; 164 else 165 m_flags &= ~lldb::eTypeOptionSkipReferences; 166 return *this; 167 } 168 169 uint32_t 170 GetValue () 171 { 172 return m_flags; 173 } 174 175 void 176 SetValue (uint32_t value) 177 { 178 m_flags = value; 179 } 180 181 private: 182 uint32_t m_flags; 183 }; 184 185 SyntheticChildren (const Flags& flags) : 186 m_flags(flags) 187 { 188 } 189 190 virtual 191 ~SyntheticChildren () 192 { 193 } 194 195 bool 196 Cascades () const 197 { 198 return m_flags.GetCascades(); 199 } 200 bool 201 SkipsPointers () const 202 { 203 return m_flags.GetSkipPointers(); 204 } 205 bool 206 SkipsReferences () const 207 { 208 return m_flags.GetSkipReferences(); 209 } 210 211 void 212 SetCascades (bool value) 213 { 214 m_flags.SetCascades(value); 215 } 216 217 void 218 SetSkipsPointers (bool value) 219 { 220 m_flags.SetSkipPointers(value); 221 } 222 223 void 224 SetSkipsReferences (bool value) 225 { 226 m_flags.SetSkipReferences(value); 227 } 228 229 uint32_t 230 GetOptions () 231 { 232 return m_flags.GetValue(); 233 } 234 235 void 236 SetOptions (uint32_t value) 237 { 238 m_flags.SetValue(value); 239 } 240 241 virtual bool 242 IsScripted () = 0; 243 244 virtual std::string 245 GetDescription () = 0; 246 247 virtual SyntheticChildrenFrontEnd::AutoPointer 248 GetFrontEnd (ValueObject &backend) = 0; 249 250 typedef STD_SHARED_PTR(SyntheticChildren) SharedPointer; 251 typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&); 252 253 uint32_t& 254 GetRevision () 255 { 256 return m_my_revision; 257 } 258 259 protected: 260 uint32_t m_my_revision; 261 Flags m_flags; 262 263 private: 264 DISALLOW_COPY_AND_ASSIGN(SyntheticChildren); 265 }; 266 267 class TypeFilterImpl : public SyntheticChildren 268 { 269 std::vector<std::string> m_expression_paths; 270 public: 271 TypeFilterImpl(const SyntheticChildren::Flags& flags) : 272 SyntheticChildren(flags), 273 m_expression_paths() 274 { 275 } 276 277 void 278 AddExpressionPath (const char* path) 279 { 280 AddExpressionPath(std::string(path)); 281 } 282 283 void 284 Clear() 285 { 286 m_expression_paths.clear(); 287 } 288 289 int 290 GetCount() const 291 { 292 return m_expression_paths.size(); 293 } 294 295 const char* 296 GetExpressionPathAtIndex(int i) const 297 { 298 return m_expression_paths[i].c_str(); 299 } 300 301 bool 302 SetExpressionPathAtIndex (int i, const char* path) 303 { 304 return SetExpressionPathAtIndex(i, std::string(path)); 305 } 306 307 void 308 AddExpressionPath (std::string path) 309 { 310 bool need_add_dot = true; 311 if (path[0] == '.' || 312 (path[0] == '-' && path[1] == '>') || 313 path[0] == '[') 314 need_add_dot = false; 315 // add a '.' symbol to help forgetful users 316 if(!need_add_dot) 317 m_expression_paths.push_back(path); 318 else 319 m_expression_paths.push_back(std::string(".") + path); 320 } 321 322 bool 323 SetExpressionPathAtIndex (int i, std::string path) 324 { 325 if (i >= GetCount()) 326 return false; 327 bool need_add_dot = true; 328 if (path[0] == '.' || 329 (path[0] == '-' && path[1] == '>') || 330 path[0] == '[') 331 need_add_dot = false; 332 // add a '.' symbol to help forgetful users 333 if(!need_add_dot) 334 m_expression_paths[i] = path; 335 else 336 m_expression_paths[i] = std::string(".") + path; 337 return true; 338 } 339 340 bool 341 IsScripted () 342 { 343 return false; 344 } 345 346 std::string 347 GetDescription (); 348 349 class FrontEnd : public SyntheticChildrenFrontEnd 350 { 351 private: 352 TypeFilterImpl* filter; 353 public: 354 355 FrontEnd(TypeFilterImpl* flt, 356 ValueObject &backend) : 357 SyntheticChildrenFrontEnd(backend), 358 filter(flt) 359 {} 360 361 virtual 362 ~FrontEnd () 363 { 364 } 365 366 virtual size_t 367 CalculateNumChildren () 368 { 369 return filter->GetCount(); 370 } 371 372 virtual lldb::ValueObjectSP 373 GetChildAtIndex (size_t idx) 374 { 375 if (idx >= filter->GetCount()) 376 return lldb::ValueObjectSP(); 377 return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true); 378 } 379 380 virtual bool 381 Update() { return false; } 382 383 virtual bool 384 MightHaveChildren () 385 { 386 return filter->GetCount() > 0; 387 } 388 389 virtual size_t 390 GetIndexOfChildWithName (const ConstString &name) 391 { 392 const char* name_cstr = name.GetCString(); 393 for (int i = 0; i < filter->GetCount(); i++) 394 { 395 const char* expr_cstr = filter->GetExpressionPathAtIndex(i); 396 if (expr_cstr) 397 { 398 if (*expr_cstr == '.') 399 expr_cstr++; 400 else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') 401 expr_cstr += 2; 402 } 403 if (!::strcmp(name_cstr, expr_cstr)) 404 return i; 405 } 406 return UINT32_MAX; 407 } 408 409 typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; 410 411 private: 412 DISALLOW_COPY_AND_ASSIGN(FrontEnd); 413 }; 414 415 virtual SyntheticChildrenFrontEnd::AutoPointer 416 GetFrontEnd(ValueObject &backend) 417 { 418 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); 419 } 420 421 private: 422 DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl); 423 }; 424 425 class CXXSyntheticChildren : public SyntheticChildren 426 { 427 public: 428 typedef SyntheticChildrenFrontEnd* (*CreateFrontEndCallback) (CXXSyntheticChildren*, lldb::ValueObjectSP); 429 protected: 430 CreateFrontEndCallback m_create_callback; 431 std::string m_description; 432 public: 433 CXXSyntheticChildren (const SyntheticChildren::Flags& flags, 434 const char* description, 435 CreateFrontEndCallback callback) : 436 SyntheticChildren(flags), 437 m_create_callback(callback), 438 m_description(description ? description : "") 439 { 440 } 441 442 bool 443 IsScripted () 444 { 445 return false; 446 } 447 448 std::string 449 GetDescription (); 450 451 virtual SyntheticChildrenFrontEnd::AutoPointer 452 GetFrontEnd (ValueObject &backend) 453 { 454 return SyntheticChildrenFrontEnd::AutoPointer(m_create_callback(this, backend.GetSP())); 455 } 456 457 private: 458 DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren); 459 }; 460 461#ifndef LLDB_DISABLE_PYTHON 462 463 class ScriptedSyntheticChildren : public SyntheticChildren 464 { 465 std::string m_python_class; 466 std::string m_python_code; 467 public: 468 469 ScriptedSyntheticChildren (const SyntheticChildren::Flags& flags, 470 const char* pclass, 471 const char* pcode = NULL) : 472 SyntheticChildren(flags), 473 m_python_class(), 474 m_python_code() 475 { 476 if (pclass) 477 m_python_class = pclass; 478 if (pcode) 479 m_python_code = pcode; 480 } 481 482 const char* 483 GetPythonClassName () 484 { 485 return m_python_class.c_str(); 486 } 487 488 const char* 489 GetPythonCode () 490 { 491 return m_python_code.c_str(); 492 } 493 494 void 495 SetPythonClassName (const char* fname) 496 { 497 m_python_class.assign(fname); 498 m_python_code.clear(); 499 } 500 501 void 502 SetPythonCode (const char* script) 503 { 504 m_python_code.assign(script); 505 } 506 507 std::string 508 GetDescription (); 509 510 bool 511 IsScripted () 512 { 513 return true; 514 } 515 516 class FrontEnd : public SyntheticChildrenFrontEnd 517 { 518 private: 519 std::string m_python_class; 520 lldb::ScriptInterpreterObjectSP m_wrapper_sp; 521 ScriptInterpreter *m_interpreter; 522 public: 523 524 FrontEnd (std::string pclass, 525 ValueObject &backend); 526 527 virtual 528 ~FrontEnd (); 529 530 virtual size_t 531 CalculateNumChildren () 532 { 533 if (!m_wrapper_sp || m_interpreter == NULL) 534 return 0; 535 return m_interpreter->CalculateNumChildren(m_wrapper_sp); 536 } 537 538 virtual lldb::ValueObjectSP 539 GetChildAtIndex (size_t idx); 540 541 virtual bool 542 Update () 543 { 544 if (!m_wrapper_sp || m_interpreter == NULL) 545 return false; 546 547 return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); 548 } 549 550 virtual bool 551 MightHaveChildren () 552 { 553 if (!m_wrapper_sp || m_interpreter == NULL) 554 return false; 555 556 return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); 557 } 558 559 virtual size_t 560 GetIndexOfChildWithName (const ConstString &name) 561 { 562 if (!m_wrapper_sp || m_interpreter == NULL) 563 return UINT32_MAX; 564 return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString()); 565 } 566 567 typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; 568 569 private: 570 DISALLOW_COPY_AND_ASSIGN(FrontEnd); 571 }; 572 573 virtual SyntheticChildrenFrontEnd::AutoPointer 574 GetFrontEnd(ValueObject &backend) 575 { 576 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); 577 } 578 579 private: 580 DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren); 581 }; 582#endif 583} // namespace lldb_private 584 585#endif // lldb_TypeSynthetic_h_ 586