forked from OSchip/llvm-project
659 lines
21 KiB
C++
659 lines
21 KiB
C++
//===-- OptionValueProperties.cpp -----------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Interpreter/OptionValueProperties.h"
|
|
|
|
#include "lldb/Utility/Flags.h"
|
|
|
|
#include "lldb/Core/UserSettingsController.h"
|
|
#include "lldb/Interpreter/OptionValues.h"
|
|
#include "lldb/Interpreter/Property.h"
|
|
#include "lldb/Utility/Args.h"
|
|
#include "lldb/Utility/Stream.h"
|
|
#include "lldb/Utility/StringList.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
OptionValueProperties::OptionValueProperties(ConstString name) : m_name(name) {}
|
|
|
|
size_t OptionValueProperties::GetNumProperties() const {
|
|
return m_properties.size();
|
|
}
|
|
|
|
void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
|
|
for (const auto &definition : defs) {
|
|
Property property(definition);
|
|
assert(property.IsValid());
|
|
m_name_to_index.Append(ConstString(property.GetName()), m_properties.size());
|
|
property.GetValue()->SetParent(shared_from_this());
|
|
m_properties.push_back(property);
|
|
}
|
|
m_name_to_index.Sort();
|
|
}
|
|
|
|
void OptionValueProperties::SetValueChangedCallback(
|
|
uint32_t property_idx, std::function<void()> callback) {
|
|
Property *property = ProtectedGetPropertyAtIndex(property_idx);
|
|
if (property)
|
|
property->SetValueChangedCallback(std::move(callback));
|
|
}
|
|
|
|
void OptionValueProperties::AppendProperty(ConstString name,
|
|
ConstString desc,
|
|
bool is_global,
|
|
const OptionValueSP &value_sp) {
|
|
Property property(name, desc, is_global, value_sp);
|
|
m_name_to_index.Append(name, m_properties.size());
|
|
m_properties.push_back(property);
|
|
value_sp->SetParent(shared_from_this());
|
|
m_name_to_index.Sort();
|
|
}
|
|
|
|
// bool
|
|
// OptionValueProperties::GetQualifiedName (Stream &strm)
|
|
//{
|
|
// bool dumped_something = false;
|
|
//// lldb::OptionValuePropertiesSP parent_sp(GetParent ());
|
|
//// if (parent_sp)
|
|
//// {
|
|
//// parent_sp->GetQualifiedName (strm);
|
|
//// strm.PutChar('.');
|
|
//// dumped_something = true;
|
|
//// }
|
|
// if (m_name)
|
|
// {
|
|
// strm << m_name;
|
|
// dumped_something = true;
|
|
// }
|
|
// return dumped_something;
|
|
//}
|
|
//
|
|
lldb::OptionValueSP
|
|
OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
|
|
ConstString key,
|
|
bool will_modify) const {
|
|
lldb::OptionValueSP value_sp;
|
|
size_t idx = m_name_to_index.Find(key, SIZE_MAX);
|
|
if (idx < m_properties.size())
|
|
value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
|
|
return value_sp;
|
|
}
|
|
|
|
lldb::OptionValueSP
|
|
OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
|
|
llvm::StringRef name, bool will_modify,
|
|
Status &error) const {
|
|
lldb::OptionValueSP value_sp;
|
|
if (name.empty())
|
|
return OptionValueSP();
|
|
|
|
llvm::StringRef sub_name;
|
|
ConstString key;
|
|
size_t key_len = name.find_first_of(".[{");
|
|
if (key_len != llvm::StringRef::npos) {
|
|
key.SetString(name.take_front(key_len));
|
|
sub_name = name.drop_front(key_len);
|
|
} else
|
|
key.SetString(name);
|
|
|
|
value_sp = GetValueForKey(exe_ctx, key, will_modify);
|
|
if (sub_name.empty() || !value_sp)
|
|
return value_sp;
|
|
|
|
switch (sub_name[0]) {
|
|
case '.': {
|
|
lldb::OptionValueSP return_val_sp;
|
|
return_val_sp =
|
|
value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error);
|
|
if (!return_val_sp) {
|
|
if (Properties::IsSettingExperimental(sub_name.drop_front())) {
|
|
size_t experimental_len =
|
|
strlen(Properties::GetExperimentalSettingsName());
|
|
if (sub_name[experimental_len + 1] == '.')
|
|
return_val_sp = value_sp->GetSubValue(
|
|
exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error);
|
|
// It isn't an error if an experimental setting is not present.
|
|
if (!return_val_sp)
|
|
error.Clear();
|
|
}
|
|
}
|
|
return return_val_sp;
|
|
}
|
|
case '[':
|
|
// Array or dictionary access for subvalues like: "[12]" -- access
|
|
// 12th array element "['hello']" -- dictionary access of key named hello
|
|
return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
|
|
|
|
default:
|
|
value_sp.reset();
|
|
break;
|
|
}
|
|
return value_sp;
|
|
}
|
|
|
|
Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
|
|
VarSetOperationType op,
|
|
llvm::StringRef name,
|
|
llvm::StringRef value) {
|
|
Status error;
|
|
const bool will_modify = true;
|
|
llvm::SmallVector<llvm::StringRef, 8> components;
|
|
name.split(components, '.');
|
|
bool name_contains_experimental = false;
|
|
for (const auto &part : components)
|
|
if (Properties::IsSettingExperimental(part))
|
|
name_contains_experimental = true;
|
|
|
|
lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
|
|
if (value_sp)
|
|
error = value_sp->SetValueFromString(value, op);
|
|
else {
|
|
// Don't set an error if the path contained .experimental. - those are
|
|
// allowed to be missing and should silently fail.
|
|
if (!name_contains_experimental && error.AsCString() == nullptr) {
|
|
error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
uint32_t
|
|
OptionValueProperties::GetPropertyIndex(ConstString name) const {
|
|
return m_name_to_index.Find(name, SIZE_MAX);
|
|
}
|
|
|
|
const Property *
|
|
OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
|
|
bool will_modify,
|
|
ConstString name) const {
|
|
return GetPropertyAtIndex(
|
|
exe_ctx, will_modify,
|
|
m_name_to_index.Find(name, SIZE_MAX));
|
|
}
|
|
|
|
const Property *OptionValueProperties::GetPropertyAtIndex(
|
|
const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
|
|
return ProtectedGetPropertyAtIndex(idx);
|
|
}
|
|
|
|
lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
|
|
const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
|
|
const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx);
|
|
if (setting)
|
|
return setting->GetValue();
|
|
return OptionValueSP();
|
|
}
|
|
|
|
OptionValuePathMappings *
|
|
OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
|
|
const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
|
|
OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
|
|
if (value_sp)
|
|
return value_sp->GetAsPathMappings();
|
|
return nullptr;
|
|
}
|
|
|
|
OptionValueFileSpecList *
|
|
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
|
|
const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
|
|
OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
|
|
if (value_sp)
|
|
return value_sp->GetAsFileSpecList();
|
|
return nullptr;
|
|
}
|
|
|
|
OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
|
|
const ExecutionContext *exe_ctx, uint32_t idx) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property)
|
|
return property->GetValue()->GetAsArch();
|
|
return nullptr;
|
|
}
|
|
|
|
OptionValueLanguage *
|
|
OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
|
|
const ExecutionContext *exe_ctx, uint32_t idx) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property)
|
|
return property->GetValue()->GetAsLanguage();
|
|
return nullptr;
|
|
}
|
|
|
|
bool OptionValueProperties::GetPropertyAtIndexAsArgs(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (!property)
|
|
return false;
|
|
|
|
OptionValue *value = property->GetValue().get();
|
|
if (!value)
|
|
return false;
|
|
|
|
const OptionValueArgs *arguments = value->GetAsArgs();
|
|
if (arguments)
|
|
return arguments->GetArgs(args);
|
|
|
|
const OptionValueArray *array = value->GetAsArray();
|
|
if (array)
|
|
return array->GetArgs(args);
|
|
|
|
const OptionValueDictionary *dict = value->GetAsDictionary();
|
|
if (dict)
|
|
return dict->GetArgs(args);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool OptionValueProperties::SetPropertyAtIndexFromArgs(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (!property)
|
|
return false;
|
|
|
|
OptionValue *value = property->GetValue().get();
|
|
if (!value)
|
|
return false;
|
|
|
|
OptionValueArgs *arguments = value->GetAsArgs();
|
|
if (arguments)
|
|
return arguments->SetArgs(args, eVarSetOperationAssign).Success();
|
|
|
|
OptionValueArray *array = value->GetAsArray();
|
|
if (array)
|
|
return array->SetArgs(args, eVarSetOperationAssign).Success();
|
|
|
|
OptionValueDictionary *dict = value->GetAsDictionary();
|
|
if (dict)
|
|
return dict->SetArgs(args, eVarSetOperationAssign).Success();
|
|
|
|
return false;
|
|
}
|
|
|
|
bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetBooleanValue(fail_value);
|
|
}
|
|
return fail_value;
|
|
}
|
|
|
|
bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value) {
|
|
value->SetBooleanValue(new_value);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
OptionValueDictionary *
|
|
OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
|
|
const ExecutionContext *exe_ctx, uint32_t idx) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property)
|
|
return property->GetValue()->GetAsDictionary();
|
|
return nullptr;
|
|
}
|
|
|
|
int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetEnumerationValue(fail_value);
|
|
}
|
|
return fail_value;
|
|
}
|
|
|
|
bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->SetEnumerationValue(new_value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const FormatEntity::Entry *
|
|
OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
|
|
const ExecutionContext *exe_ctx, uint32_t idx) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetFormatEntity();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
OptionValueFileSpec *
|
|
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
|
|
const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetAsFileSpec();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
|
|
const ExecutionContext *exe_ctx, uint32_t idx) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetFileSpecValue();
|
|
}
|
|
return FileSpec();
|
|
}
|
|
|
|
bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
|
|
const ExecutionContext *exe_ctx, uint32_t idx,
|
|
const FileSpec &new_file_spec) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->SetFileSpecValue(new_file_spec);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const RegularExpression *
|
|
OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
|
|
const ExecutionContext *exe_ctx, uint32_t idx) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetRegexValue();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
|
|
const ExecutionContext *exe_ctx, uint32_t idx) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetAsSInt64();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetSInt64Value(fail_value);
|
|
}
|
|
return fail_value;
|
|
}
|
|
|
|
bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->SetSInt64Value(new_value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
|
|
const ExecutionContext *exe_ctx, uint32_t idx,
|
|
llvm::StringRef fail_value) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetStringValue(fail_value);
|
|
}
|
|
return fail_value;
|
|
}
|
|
|
|
bool OptionValueProperties::SetPropertyAtIndexAsString(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->SetStringValue(new_value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
|
|
const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
|
|
OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
|
|
if (value_sp)
|
|
return value_sp->GetAsString();
|
|
return nullptr;
|
|
}
|
|
|
|
uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->GetUInt64Value(fail_value);
|
|
}
|
|
return fail_value;
|
|
}
|
|
|
|
bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
|
|
const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
|
|
if (property) {
|
|
OptionValue *value = property->GetValue().get();
|
|
if (value)
|
|
return value->SetUInt64Value(new_value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void OptionValueProperties::Clear() {
|
|
const size_t num_properties = m_properties.size();
|
|
for (size_t i = 0; i < num_properties; ++i)
|
|
m_properties[i].GetValue()->Clear();
|
|
}
|
|
|
|
Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
|
|
VarSetOperationType op) {
|
|
Status error;
|
|
|
|
// Args args(value_cstr);
|
|
// const size_t argc = args.GetArgumentCount();
|
|
switch (op) {
|
|
case eVarSetOperationClear:
|
|
Clear();
|
|
break;
|
|
|
|
case eVarSetOperationReplace:
|
|
case eVarSetOperationAssign:
|
|
case eVarSetOperationRemove:
|
|
case eVarSetOperationInsertBefore:
|
|
case eVarSetOperationInsertAfter:
|
|
case eVarSetOperationAppend:
|
|
case eVarSetOperationInvalid:
|
|
error = OptionValue::SetValueFromString(value, op);
|
|
break;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
|
|
Stream &strm, uint32_t dump_mask) {
|
|
const size_t num_properties = m_properties.size();
|
|
for (size_t i = 0; i < num_properties; ++i) {
|
|
const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
|
|
if (property) {
|
|
OptionValue *option_value = property->GetValue().get();
|
|
assert(option_value);
|
|
const bool transparent_value = option_value->ValueIsTransparent();
|
|
property->Dump(exe_ctx, strm, dump_mask);
|
|
if (!transparent_value)
|
|
strm.EOL();
|
|
}
|
|
}
|
|
}
|
|
|
|
Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
|
|
Stream &strm,
|
|
llvm::StringRef property_path,
|
|
uint32_t dump_mask) {
|
|
Status error;
|
|
const bool will_modify = false;
|
|
lldb::OptionValueSP value_sp(
|
|
GetSubValue(exe_ctx, property_path, will_modify, error));
|
|
if (value_sp) {
|
|
if (!value_sp->ValueIsTransparent()) {
|
|
if (dump_mask & eDumpOptionName)
|
|
strm.PutCString(property_path);
|
|
if (dump_mask & ~eDumpOptionName)
|
|
strm.PutChar(' ');
|
|
}
|
|
value_sp->DumpValue(exe_ctx, strm, dump_mask);
|
|
}
|
|
return error;
|
|
}
|
|
|
|
OptionValuePropertiesSP
|
|
OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {
|
|
auto global_props_sp = global_properties.GetValueProperties();
|
|
lldbassert(global_props_sp);
|
|
|
|
auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
|
|
return std::static_pointer_cast<OptionValueProperties>(copy_sp);
|
|
}
|
|
|
|
OptionValueSP
|
|
OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {
|
|
auto copy_sp = OptionValue::DeepCopy(new_parent);
|
|
// copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
|
|
// types that override GetType returning a different value.
|
|
auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
|
|
lldbassert(props_value_ptr);
|
|
|
|
for (auto &property : props_value_ptr->m_properties) {
|
|
// Duplicate any values that are not global when constructing properties
|
|
// from a global copy.
|
|
if (!property.IsGlobal()) {
|
|
auto value_sp = property.GetValue()->DeepCopy(copy_sp);
|
|
property.SetOptionValue(value_sp);
|
|
}
|
|
}
|
|
return copy_sp;
|
|
}
|
|
|
|
const Property *OptionValueProperties::GetPropertyAtPath(
|
|
const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const {
|
|
const Property *property = nullptr;
|
|
if (name.empty())
|
|
return nullptr;
|
|
llvm::StringRef sub_name;
|
|
ConstString key;
|
|
size_t key_len = name.find_first_of(".[{");
|
|
|
|
if (key_len != llvm::StringRef::npos) {
|
|
key.SetString(name.take_front(key_len));
|
|
sub_name = name.drop_front(key_len);
|
|
} else
|
|
key.SetString(name);
|
|
|
|
property = GetProperty(exe_ctx, will_modify, key);
|
|
if (sub_name.empty() || !property)
|
|
return property;
|
|
|
|
if (sub_name[0] == '.') {
|
|
OptionValueProperties *sub_properties =
|
|
property->GetValue()->GetAsProperties();
|
|
if (sub_properties)
|
|
return sub_properties->GetPropertyAtPath(exe_ctx, will_modify,
|
|
sub_name.drop_front());
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
|
|
Stream &strm) const {
|
|
size_t max_name_len = 0;
|
|
const size_t num_properties = m_properties.size();
|
|
for (size_t i = 0; i < num_properties; ++i) {
|
|
const Property *property = ProtectedGetPropertyAtIndex(i);
|
|
if (property)
|
|
max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
|
|
}
|
|
for (size_t i = 0; i < num_properties; ++i) {
|
|
const Property *property = ProtectedGetPropertyAtIndex(i);
|
|
if (property)
|
|
property->DumpDescription(interpreter, strm, max_name_len, false);
|
|
}
|
|
}
|
|
|
|
void OptionValueProperties::Apropos(
|
|
llvm::StringRef keyword,
|
|
std::vector<const Property *> &matching_properties) const {
|
|
const size_t num_properties = m_properties.size();
|
|
StreamString strm;
|
|
for (size_t i = 0; i < num_properties; ++i) {
|
|
const Property *property = ProtectedGetPropertyAtIndex(i);
|
|
if (property) {
|
|
const OptionValueProperties *properties =
|
|
property->GetValue()->GetAsProperties();
|
|
if (properties) {
|
|
properties->Apropos(keyword, matching_properties);
|
|
} else {
|
|
bool match = false;
|
|
llvm::StringRef name = property->GetName();
|
|
if (name.contains_lower(keyword))
|
|
match = true;
|
|
else {
|
|
llvm::StringRef desc = property->GetDescription();
|
|
if (desc.contains_lower(keyword))
|
|
match = true;
|
|
}
|
|
if (match) {
|
|
matching_properties.push_back(property);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lldb::OptionValuePropertiesSP
|
|
OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
|
|
ConstString name) {
|
|
lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
|
|
if (option_value_sp) {
|
|
OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
|
|
if (ov_properties)
|
|
return ov_properties->shared_from_this();
|
|
}
|
|
return lldb::OptionValuePropertiesSP();
|
|
}
|