1 //===-- OptionValueProperties.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/Interpreter/OptionValueProperties.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Utility/Flags.h" 17 18 #include "lldb/Core/UserSettingsController.h" 19 #include "lldb/Interpreter/OptionValues.h" 20 #include "lldb/Interpreter/Property.h" 21 #include "lldb/Utility/Args.h" 22 #include "lldb/Utility/Stream.h" 23 #include "lldb/Utility/StringList.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 OptionValueProperties::OptionValueProperties(const ConstString &name) 29 : OptionValue(), m_name(name), m_properties(), m_name_to_index() {} 30 31 OptionValueProperties::OptionValueProperties( 32 const OptionValueProperties &global_properties) 33 : OptionValue(global_properties), 34 std::enable_shared_from_this<OptionValueProperties>(), 35 m_name(global_properties.m_name), 36 m_properties(global_properties.m_properties), 37 m_name_to_index(global_properties.m_name_to_index) { 38 // We now have an exact copy of "global_properties". We need to now find all 39 // non-global settings and copy the property values so that all non-global 40 // settings get new OptionValue instances created for them. 41 const size_t num_properties = m_properties.size(); 42 for (size_t i = 0; i < num_properties; ++i) { 43 // Duplicate any values that are not global when constructing properties 44 // from a global copy 45 if (m_properties[i].IsGlobal() == false) { 46 lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy()); 47 m_properties[i].SetOptionValue(new_value_sp); 48 } 49 } 50 } 51 52 size_t OptionValueProperties::GetNumProperties() const { 53 return m_properties.size(); 54 } 55 56 void OptionValueProperties::Initialize(const PropertyDefinition *defs) { 57 for (size_t i = 0; defs[i].name; ++i) { 58 Property property(defs[i]); 59 assert(property.IsValid()); 60 m_name_to_index.Append(ConstString(property.GetName()), m_properties.size()); 61 property.GetValue()->SetParent(shared_from_this()); 62 m_properties.push_back(property); 63 } 64 m_name_to_index.Sort(); 65 } 66 67 void OptionValueProperties::SetValueChangedCallback( 68 uint32_t property_idx, OptionValueChangedCallback callback, void *baton) { 69 Property *property = ProtectedGetPropertyAtIndex(property_idx); 70 if (property) 71 property->SetValueChangedCallback(callback, baton); 72 } 73 74 void OptionValueProperties::AppendProperty(const ConstString &name, 75 const ConstString &desc, 76 bool is_global, 77 const OptionValueSP &value_sp) { 78 Property property(name, desc, is_global, value_sp); 79 m_name_to_index.Append(name, m_properties.size()); 80 m_properties.push_back(property); 81 value_sp->SetParent(shared_from_this()); 82 m_name_to_index.Sort(); 83 } 84 85 // bool 86 // OptionValueProperties::GetQualifiedName (Stream &strm) 87 //{ 88 // bool dumped_something = false; 89 //// lldb::OptionValuePropertiesSP parent_sp(GetParent ()); 90 //// if (parent_sp) 91 //// { 92 //// parent_sp->GetQualifiedName (strm); 93 //// strm.PutChar('.'); 94 //// dumped_something = true; 95 //// } 96 // if (m_name) 97 // { 98 // strm << m_name; 99 // dumped_something = true; 100 // } 101 // return dumped_something; 102 //} 103 // 104 lldb::OptionValueSP 105 OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx, 106 const ConstString &key, 107 bool will_modify) const { 108 lldb::OptionValueSP value_sp; 109 size_t idx = m_name_to_index.Find(key, SIZE_MAX); 110 if (idx < m_properties.size()) 111 value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue(); 112 return value_sp; 113 } 114 115 lldb::OptionValueSP 116 OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx, 117 llvm::StringRef name, bool will_modify, 118 Status &error) const { 119 lldb::OptionValueSP value_sp; 120 if (name.empty()) 121 return OptionValueSP(); 122 123 llvm::StringRef sub_name; 124 ConstString key; 125 size_t key_len = name.find_first_of(".[{"); 126 if (key_len != llvm::StringRef::npos) { 127 key.SetString(name.take_front(key_len)); 128 sub_name = name.drop_front(key_len); 129 } else 130 key.SetString(name); 131 132 value_sp = GetValueForKey(exe_ctx, key, will_modify); 133 if (sub_name.empty() || !value_sp) 134 return value_sp; 135 136 switch (sub_name[0]) { 137 case '.': { 138 lldb::OptionValueSP return_val_sp; 139 return_val_sp = 140 value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error); 141 if (!return_val_sp) { 142 if (Properties::IsSettingExperimental(sub_name.drop_front())) { 143 size_t experimental_len = 144 strlen(Properties::GetExperimentalSettingsName()); 145 if (sub_name[experimental_len + 1] == '.') 146 return_val_sp = value_sp->GetSubValue( 147 exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error); 148 // It isn't an error if an experimental setting is not present. 149 if (!return_val_sp) 150 error.Clear(); 151 } 152 } 153 return return_val_sp; 154 } 155 case '{': 156 // Predicate matching for predicates like 157 // "<setting-name>{<predicate>}" 158 // strings are parsed by the current OptionValueProperties subclass to mean 159 // whatever they want to. For instance a subclass of OptionValueProperties 160 // for a lldb_private::Target might implement: "target.run- 161 // args{arch==i386}" -- only set run args if the arch is i386 "target 162 // .run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path 163 // matches "target.run-args{basename==test&&arch==x86_64}" -- only set run 164 // args if executable basename is "test" and arch is "x86_64" 165 if (sub_name[1]) { 166 llvm::StringRef predicate_start = sub_name.drop_front(); 167 size_t pos = predicate_start.find_first_of('}'); 168 if (pos != llvm::StringRef::npos) { 169 auto predicate = predicate_start.take_front(pos); 170 auto rest = predicate_start.drop_front(pos); 171 if (PredicateMatches(exe_ctx, predicate)) { 172 if (!rest.empty()) { 173 // Still more subvalue string to evaluate 174 return value_sp->GetSubValue(exe_ctx, rest, 175 will_modify, error); 176 } else { 177 // We have a match! 178 break; 179 } 180 } 181 } 182 } 183 // Predicate didn't match or wasn't correctly formed 184 value_sp.reset(); 185 break; 186 187 case '[': 188 // Array or dictionary access for subvalues like: "[12]" -- access 189 // 12th array element "['hello']" -- dictionary access of key named hello 190 return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error); 191 192 default: 193 value_sp.reset(); 194 break; 195 } 196 return value_sp; 197 } 198 199 Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx, 200 VarSetOperationType op, 201 llvm::StringRef name, 202 llvm::StringRef value) { 203 Status error; 204 const bool will_modify = true; 205 llvm::SmallVector<llvm::StringRef, 8> components; 206 name.split(components, '.'); 207 bool name_contains_experimental = false; 208 for (const auto &part : components) 209 if (Properties::IsSettingExperimental(part)) 210 name_contains_experimental = true; 211 212 213 lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error)); 214 if (value_sp) 215 error = value_sp->SetValueFromString(value, op); 216 else { 217 // Don't set an error if the path contained .experimental. - those are 218 // allowed to be missing and should silently fail. 219 if (name_contains_experimental == false && error.AsCString() == nullptr) { 220 error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str()); 221 } 222 } 223 return error; 224 } 225 226 uint32_t 227 OptionValueProperties::GetPropertyIndex(const ConstString &name) const { 228 return m_name_to_index.Find(name, SIZE_MAX); 229 } 230 231 const Property * 232 OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx, 233 bool will_modify, 234 const ConstString &name) const { 235 return GetPropertyAtIndex( 236 exe_ctx, will_modify, 237 m_name_to_index.Find(name, SIZE_MAX)); 238 } 239 240 const Property *OptionValueProperties::GetPropertyAtIndex( 241 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 242 return ProtectedGetPropertyAtIndex(idx); 243 } 244 245 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex( 246 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 247 const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx); 248 if (setting) 249 return setting->GetValue(); 250 return OptionValueSP(); 251 } 252 253 OptionValuePathMappings * 254 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings( 255 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 256 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); 257 if (value_sp) 258 return value_sp->GetAsPathMappings(); 259 return nullptr; 260 } 261 262 OptionValueFileSpecList * 263 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList( 264 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 265 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); 266 if (value_sp) 267 return value_sp->GetAsFileSpecList(); 268 return nullptr; 269 } 270 271 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch( 272 const ExecutionContext *exe_ctx, uint32_t idx) const { 273 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 274 if (property) 275 return property->GetValue()->GetAsArch(); 276 return nullptr; 277 } 278 279 OptionValueLanguage * 280 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage( 281 const ExecutionContext *exe_ctx, uint32_t idx) const { 282 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 283 if (property) 284 return property->GetValue()->GetAsLanguage(); 285 return nullptr; 286 } 287 288 bool OptionValueProperties::GetPropertyAtIndexAsArgs( 289 const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const { 290 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 291 if (property) { 292 OptionValue *value = property->GetValue().get(); 293 if (value) { 294 const OptionValueArray *array = value->GetAsArray(); 295 if (array) 296 return array->GetArgs(args); 297 else { 298 const OptionValueDictionary *dict = value->GetAsDictionary(); 299 if (dict) 300 return dict->GetArgs(args); 301 } 302 } 303 } 304 return false; 305 } 306 307 bool OptionValueProperties::SetPropertyAtIndexFromArgs( 308 const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) { 309 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 310 if (property) { 311 OptionValue *value = property->GetValue().get(); 312 if (value) { 313 OptionValueArray *array = value->GetAsArray(); 314 if (array) 315 return array->SetArgs(args, eVarSetOperationAssign).Success(); 316 else { 317 OptionValueDictionary *dict = value->GetAsDictionary(); 318 if (dict) 319 return dict->SetArgs(args, eVarSetOperationAssign).Success(); 320 } 321 } 322 } 323 return false; 324 } 325 326 bool OptionValueProperties::GetPropertyAtIndexAsBoolean( 327 const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const { 328 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 329 if (property) { 330 OptionValue *value = property->GetValue().get(); 331 if (value) 332 return value->GetBooleanValue(fail_value); 333 } 334 return fail_value; 335 } 336 337 bool OptionValueProperties::SetPropertyAtIndexAsBoolean( 338 const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) { 339 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 340 if (property) { 341 OptionValue *value = property->GetValue().get(); 342 if (value) { 343 value->SetBooleanValue(new_value); 344 return true; 345 } 346 } 347 return false; 348 } 349 350 OptionValueDictionary * 351 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary( 352 const ExecutionContext *exe_ctx, uint32_t idx) const { 353 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 354 if (property) 355 return property->GetValue()->GetAsDictionary(); 356 return nullptr; 357 } 358 359 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration( 360 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const { 361 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 362 if (property) { 363 OptionValue *value = property->GetValue().get(); 364 if (value) 365 return value->GetEnumerationValue(fail_value); 366 } 367 return fail_value; 368 } 369 370 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration( 371 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) { 372 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 373 if (property) { 374 OptionValue *value = property->GetValue().get(); 375 if (value) 376 return value->SetEnumerationValue(new_value); 377 } 378 return false; 379 } 380 381 const FormatEntity::Entry * 382 OptionValueProperties::GetPropertyAtIndexAsFormatEntity( 383 const ExecutionContext *exe_ctx, uint32_t idx) { 384 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 385 if (property) { 386 OptionValue *value = property->GetValue().get(); 387 if (value) 388 return value->GetFormatEntity(); 389 } 390 return nullptr; 391 } 392 393 OptionValueFileSpec * 394 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec( 395 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 396 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 397 if (property) { 398 OptionValue *value = property->GetValue().get(); 399 if (value) 400 return value->GetAsFileSpec(); 401 } 402 return nullptr; 403 } 404 405 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec( 406 const ExecutionContext *exe_ctx, uint32_t idx) const { 407 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 408 if (property) { 409 OptionValue *value = property->GetValue().get(); 410 if (value) 411 return value->GetFileSpecValue(); 412 } 413 return FileSpec(); 414 } 415 416 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec( 417 const ExecutionContext *exe_ctx, uint32_t idx, 418 const FileSpec &new_file_spec) { 419 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 420 if (property) { 421 OptionValue *value = property->GetValue().get(); 422 if (value) 423 return value->SetFileSpecValue(new_file_spec); 424 } 425 return false; 426 } 427 428 const RegularExpression * 429 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex( 430 const ExecutionContext *exe_ctx, uint32_t idx) const { 431 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 432 if (property) { 433 OptionValue *value = property->GetValue().get(); 434 if (value) 435 return value->GetRegexValue(); 436 } 437 return nullptr; 438 } 439 440 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64( 441 const ExecutionContext *exe_ctx, uint32_t idx) const { 442 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 443 if (property) { 444 OptionValue *value = property->GetValue().get(); 445 if (value) 446 return value->GetAsSInt64(); 447 } 448 return nullptr; 449 } 450 451 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64( 452 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const { 453 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 454 if (property) { 455 OptionValue *value = property->GetValue().get(); 456 if (value) 457 return value->GetSInt64Value(fail_value); 458 } 459 return fail_value; 460 } 461 462 bool OptionValueProperties::SetPropertyAtIndexAsSInt64( 463 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) { 464 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 465 if (property) { 466 OptionValue *value = property->GetValue().get(); 467 if (value) 468 return value->SetSInt64Value(new_value); 469 } 470 return false; 471 } 472 473 llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString( 474 const ExecutionContext *exe_ctx, uint32_t idx, 475 llvm::StringRef fail_value) const { 476 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 477 if (property) { 478 OptionValue *value = property->GetValue().get(); 479 if (value) 480 return value->GetStringValue(fail_value); 481 } 482 return fail_value; 483 } 484 485 bool OptionValueProperties::SetPropertyAtIndexAsString( 486 const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) { 487 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 488 if (property) { 489 OptionValue *value = property->GetValue().get(); 490 if (value) 491 return value->SetStringValue(new_value); 492 } 493 return false; 494 } 495 496 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString( 497 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 498 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); 499 if (value_sp) 500 return value_sp->GetAsString(); 501 return nullptr; 502 } 503 504 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64( 505 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const { 506 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 507 if (property) { 508 OptionValue *value = property->GetValue().get(); 509 if (value) 510 return value->GetUInt64Value(fail_value); 511 } 512 return fail_value; 513 } 514 515 bool OptionValueProperties::SetPropertyAtIndexAsUInt64( 516 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) { 517 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 518 if (property) { 519 OptionValue *value = property->GetValue().get(); 520 if (value) 521 return value->SetUInt64Value(new_value); 522 } 523 return false; 524 } 525 526 bool OptionValueProperties::Clear() { 527 const size_t num_properties = m_properties.size(); 528 for (size_t i = 0; i < num_properties; ++i) 529 m_properties[i].GetValue()->Clear(); 530 return true; 531 } 532 533 Status OptionValueProperties::SetValueFromString(llvm::StringRef value, 534 VarSetOperationType op) { 535 Status error; 536 537 // Args args(value_cstr); 538 // const size_t argc = args.GetArgumentCount(); 539 switch (op) { 540 case eVarSetOperationClear: 541 Clear(); 542 break; 543 544 case eVarSetOperationReplace: 545 case eVarSetOperationAssign: 546 case eVarSetOperationRemove: 547 case eVarSetOperationInsertBefore: 548 case eVarSetOperationInsertAfter: 549 case eVarSetOperationAppend: 550 case eVarSetOperationInvalid: 551 error = OptionValue::SetValueFromString(value, op); 552 break; 553 } 554 555 return error; 556 } 557 558 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx, 559 Stream &strm, uint32_t dump_mask) { 560 const size_t num_properties = m_properties.size(); 561 for (size_t i = 0; i < num_properties; ++i) { 562 const Property *property = GetPropertyAtIndex(exe_ctx, false, i); 563 if (property) { 564 OptionValue *option_value = property->GetValue().get(); 565 assert(option_value); 566 const bool transparent_value = option_value->ValueIsTransparent(); 567 property->Dump(exe_ctx, strm, dump_mask); 568 if (!transparent_value) 569 strm.EOL(); 570 } 571 } 572 } 573 574 Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx, 575 Stream &strm, 576 llvm::StringRef property_path, 577 uint32_t dump_mask) { 578 Status error; 579 const bool will_modify = false; 580 lldb::OptionValueSP value_sp( 581 GetSubValue(exe_ctx, property_path, will_modify, error)); 582 if (value_sp) { 583 if (!value_sp->ValueIsTransparent()) { 584 if (dump_mask & eDumpOptionName) 585 strm.PutCString(property_path); 586 if (dump_mask & ~eDumpOptionName) 587 strm.PutChar(' '); 588 } 589 value_sp->DumpValue(exe_ctx, strm, dump_mask); 590 } 591 return error; 592 } 593 594 lldb::OptionValueSP OptionValueProperties::DeepCopy() const { 595 llvm_unreachable("this shouldn't happen"); 596 } 597 598 const Property *OptionValueProperties::GetPropertyAtPath( 599 const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const { 600 const Property *property = nullptr; 601 if (name.empty()) 602 return nullptr; 603 llvm::StringRef sub_name; 604 ConstString key; 605 size_t key_len = name.find_first_of(".[{"); 606 607 if (key_len != llvm::StringRef::npos) { 608 key.SetString(name.take_front(key_len)); 609 sub_name = name.drop_front(key_len); 610 } else 611 key.SetString(name); 612 613 property = GetProperty(exe_ctx, will_modify, key); 614 if (sub_name.empty() || !property) 615 return property; 616 617 if (sub_name[0] == '.') { 618 OptionValueProperties *sub_properties = 619 property->GetValue()->GetAsProperties(); 620 if (sub_properties) 621 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, 622 sub_name.drop_front()); 623 } 624 return nullptr; 625 } 626 627 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter, 628 Stream &strm) const { 629 size_t max_name_len = 0; 630 const size_t num_properties = m_properties.size(); 631 for (size_t i = 0; i < num_properties; ++i) { 632 const Property *property = ProtectedGetPropertyAtIndex(i); 633 if (property) 634 max_name_len = std::max<size_t>(property->GetName().size(), max_name_len); 635 } 636 for (size_t i = 0; i < num_properties; ++i) { 637 const Property *property = ProtectedGetPropertyAtIndex(i); 638 if (property) 639 property->DumpDescription(interpreter, strm, max_name_len, false); 640 } 641 } 642 643 void OptionValueProperties::Apropos( 644 llvm::StringRef keyword, 645 std::vector<const Property *> &matching_properties) const { 646 const size_t num_properties = m_properties.size(); 647 StreamString strm; 648 for (size_t i = 0; i < num_properties; ++i) { 649 const Property *property = ProtectedGetPropertyAtIndex(i); 650 if (property) { 651 const OptionValueProperties *properties = 652 property->GetValue()->GetAsProperties(); 653 if (properties) { 654 properties->Apropos(keyword, matching_properties); 655 } else { 656 bool match = false; 657 llvm::StringRef name = property->GetName(); 658 if (name.contains_lower(keyword)) 659 match = true; 660 else { 661 llvm::StringRef desc = property->GetDescription(); 662 if (desc.contains_lower(keyword)) 663 match = true; 664 } 665 if (match) { 666 matching_properties.push_back(property); 667 } 668 } 669 } 670 } 671 } 672 673 lldb::OptionValuePropertiesSP 674 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx, 675 const ConstString &name) { 676 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false)); 677 if (option_value_sp) { 678 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties(); 679 if (ov_properties) 680 return ov_properties->shared_from_this(); 681 } 682 return lldb::OptionValuePropertiesSP(); 683 } 684