1 //===-- OptionValueProperties.cpp --------------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Interpreter/OptionValueProperties.h"
14 // Other libraries and framework includes
16 #include "lldb/Utility/Flags.h"
18 #include "lldb/Core/UserSettingsController.h"
19 #include "lldb/Interpreter/Args.h"
20 #include "lldb/Interpreter/OptionValues.h"
21 #include "lldb/Interpreter/Property.h"
22 #include "lldb/Utility/Stream.h"
23 #include "lldb/Utility/StringList.h"
26 using namespace lldb_private;
28 OptionValueProperties::OptionValueProperties(const ConstString &name)
29 : OptionValue(), m_name(name), m_properties(), m_name_to_index() {}
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
39 // find all non-global settings and copy the property values so that
40 // all non-global settings get new OptionValue instances created for
42 const size_t num_properties = m_properties.size();
43 for (size_t i = 0; i < num_properties; ++i) {
44 // Duplicate any values that are not global when constructing properties
47 if (m_properties[i].IsGlobal() == false) {
48 lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy());
49 m_properties[i].SetOptionValue(new_value_sp);
54 size_t OptionValueProperties::GetNumProperties() const {
55 return m_properties.size();
58 void OptionValueProperties::Initialize(const PropertyDefinition *defs) {
59 for (size_t i = 0; defs[i].name; ++i) {
60 Property property(defs[i]);
61 assert(property.IsValid());
62 m_name_to_index.Append(property.GetName(), m_properties.size());
63 property.GetValue()->SetParent(shared_from_this());
64 m_properties.push_back(property);
66 m_name_to_index.Sort();
69 void OptionValueProperties::SetValueChangedCallback(
70 uint32_t property_idx, OptionValueChangedCallback callback, void *baton) {
71 Property *property = ProtectedGetPropertyAtIndex(property_idx);
73 property->SetValueChangedCallback(callback, baton);
76 void OptionValueProperties::AppendProperty(const ConstString &name,
77 const ConstString &desc,
79 const OptionValueSP &value_sp) {
80 Property property(name, desc, is_global, value_sp);
81 m_name_to_index.Append(name.GetStringRef(), m_properties.size());
82 m_properties.push_back(property);
83 value_sp->SetParent(shared_from_this());
84 m_name_to_index.Sort();
88 // OptionValueProperties::GetQualifiedName (Stream &strm)
90 // bool dumped_something = false;
91 //// lldb::OptionValuePropertiesSP parent_sp(GetParent ());
94 //// parent_sp->GetQualifiedName (strm);
95 //// strm.PutChar('.');
96 //// dumped_something = true;
101 // dumped_something = true;
103 // return dumped_something;
107 OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
108 const ConstString &key,
109 bool will_modify) const {
110 lldb::OptionValueSP value_sp;
111 size_t idx = m_name_to_index.Find(key.GetStringRef(), SIZE_MAX);
112 if (idx < m_properties.size())
113 value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
118 OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
119 llvm::StringRef name, bool will_modify,
120 Error &error) const {
121 lldb::OptionValueSP value_sp;
123 return OptionValueSP();
125 llvm::StringRef sub_name;
127 size_t key_len = name.find_first_of(".[{");
128 if (key_len != llvm::StringRef::npos) {
129 key.SetString(name.take_front(key_len));
130 sub_name = name.drop_front(key_len);
134 value_sp = GetValueForKey(exe_ctx, key, will_modify);
135 if (sub_name.empty() || !value_sp)
138 switch (sub_name[0]) {
140 lldb::OptionValueSP return_val_sp;
142 value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error);
143 if (!return_val_sp) {
144 if (Properties::IsSettingExperimental(sub_name.drop_front())) {
145 size_t experimental_len =
146 strlen(Properties::GetExperimentalSettingsName());
147 if (sub_name[experimental_len + 1] == '.')
148 return_val_sp = value_sp->GetSubValue(
149 exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error);
150 // It isn't an error if an experimental setting is not present.
155 return return_val_sp;
158 // Predicate matching for predicates like
159 // "<setting-name>{<predicate>}"
160 // strings are parsed by the current OptionValueProperties subclass
161 // to mean whatever they want to. For instance a subclass of
162 // OptionValueProperties for a lldb_private::Target might implement:
163 // "target.run-args{arch==i386}" -- only set run args if the arch is
165 // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the
167 // "target.run-args{basename==test&&arch==x86_64}" -- only set run args
168 // if executable basename is "test" and arch is "x86_64"
170 llvm::StringRef predicate_start = sub_name.drop_front();
171 size_t pos = predicate_start.find_first_of('}');
172 if (pos != llvm::StringRef::npos) {
173 auto predicate = predicate_start.take_front(pos);
174 auto rest = predicate_start.drop_front(pos);
175 if (PredicateMatches(exe_ctx, predicate)) {
177 // Still more subvalue string to evaluate
178 return value_sp->GetSubValue(exe_ctx, rest,
187 // Predicate didn't match or wasn't correctly formed
192 // Array or dictionary access for subvalues like:
193 // "[12]" -- access 12th array element
194 // "['hello']" -- dictionary access of key named hello
195 return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
204 Error OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
205 VarSetOperationType op,
206 llvm::StringRef name, llvm::StringRef value) {
208 const bool will_modify = true;
209 lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
211 error = value_sp->SetValueFromString(value, op);
213 if (error.AsCString() == nullptr)
214 error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
220 OptionValueProperties::GetPropertyIndex(const ConstString &name) const {
221 return m_name_to_index.Find(name.GetStringRef(), SIZE_MAX);
225 OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
227 const ConstString &name) const {
228 return GetPropertyAtIndex(
229 exe_ctx, will_modify,
230 m_name_to_index.Find(name.GetStringRef(), SIZE_MAX));
233 const Property *OptionValueProperties::GetPropertyAtIndex(
234 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
235 return ProtectedGetPropertyAtIndex(idx);
238 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
239 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
240 const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx);
242 return setting->GetValue();
243 return OptionValueSP();
246 OptionValuePathMappings *
247 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
248 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
249 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
251 return value_sp->GetAsPathMappings();
255 OptionValueFileSpecList *
256 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
257 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
258 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
260 return value_sp->GetAsFileSpecList();
264 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
265 const ExecutionContext *exe_ctx, uint32_t idx) const {
266 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
268 return property->GetValue()->GetAsArch();
272 OptionValueLanguage *
273 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
274 const ExecutionContext *exe_ctx, uint32_t idx) const {
275 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
277 return property->GetValue()->GetAsLanguage();
281 bool OptionValueProperties::GetPropertyAtIndexAsArgs(
282 const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
283 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
285 OptionValue *value = property->GetValue().get();
287 const OptionValueArray *array = value->GetAsArray();
289 return array->GetArgs(args);
291 const OptionValueDictionary *dict = value->GetAsDictionary();
293 return dict->GetArgs(args);
300 bool OptionValueProperties::SetPropertyAtIndexFromArgs(
301 const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
302 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
304 OptionValue *value = property->GetValue().get();
306 OptionValueArray *array = value->GetAsArray();
308 return array->SetArgs(args, eVarSetOperationAssign).Success();
310 OptionValueDictionary *dict = value->GetAsDictionary();
312 return dict->SetArgs(args, eVarSetOperationAssign).Success();
319 bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
320 const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
321 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
323 OptionValue *value = property->GetValue().get();
325 return value->GetBooleanValue(fail_value);
330 bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
331 const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
332 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
334 OptionValue *value = property->GetValue().get();
336 value->SetBooleanValue(new_value);
343 OptionValueDictionary *
344 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
345 const ExecutionContext *exe_ctx, uint32_t idx) const {
346 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
348 return property->GetValue()->GetAsDictionary();
352 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
353 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
354 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
356 OptionValue *value = property->GetValue().get();
358 return value->GetEnumerationValue(fail_value);
363 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
364 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
365 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
367 OptionValue *value = property->GetValue().get();
369 return value->SetEnumerationValue(new_value);
374 const FormatEntity::Entry *
375 OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
376 const ExecutionContext *exe_ctx, uint32_t idx) {
377 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
379 OptionValue *value = property->GetValue().get();
381 return value->GetFormatEntity();
386 OptionValueFileSpec *
387 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
388 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
389 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
391 OptionValue *value = property->GetValue().get();
393 return value->GetAsFileSpec();
398 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
399 const ExecutionContext *exe_ctx, uint32_t idx) const {
400 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
402 OptionValue *value = property->GetValue().get();
404 return value->GetFileSpecValue();
409 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
410 const ExecutionContext *exe_ctx, uint32_t idx,
411 const FileSpec &new_file_spec) {
412 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
414 OptionValue *value = property->GetValue().get();
416 return value->SetFileSpecValue(new_file_spec);
421 const RegularExpression *
422 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
423 const ExecutionContext *exe_ctx, uint32_t idx) const {
424 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
426 OptionValue *value = property->GetValue().get();
428 return value->GetRegexValue();
433 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
434 const ExecutionContext *exe_ctx, uint32_t idx) const {
435 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
437 OptionValue *value = property->GetValue().get();
439 return value->GetAsSInt64();
444 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
445 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
446 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
448 OptionValue *value = property->GetValue().get();
450 return value->GetSInt64Value(fail_value);
455 bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
456 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
457 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
459 OptionValue *value = property->GetValue().get();
461 return value->SetSInt64Value(new_value);
466 llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
467 const ExecutionContext *exe_ctx, uint32_t idx,
468 llvm::StringRef fail_value) const {
469 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
471 OptionValue *value = property->GetValue().get();
473 return value->GetStringValue(fail_value);
478 bool OptionValueProperties::SetPropertyAtIndexAsString(
479 const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
480 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
482 OptionValue *value = property->GetValue().get();
484 return value->SetStringValue(new_value);
489 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
490 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
491 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
493 return value_sp->GetAsString();
497 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
498 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
499 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
501 OptionValue *value = property->GetValue().get();
503 return value->GetUInt64Value(fail_value);
508 bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
509 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
510 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
512 OptionValue *value = property->GetValue().get();
514 return value->SetUInt64Value(new_value);
519 bool OptionValueProperties::Clear() {
520 const size_t num_properties = m_properties.size();
521 for (size_t i = 0; i < num_properties; ++i)
522 m_properties[i].GetValue()->Clear();
526 Error OptionValueProperties::SetValueFromString(llvm::StringRef value,
527 VarSetOperationType op) {
530 // Args args(value_cstr);
531 // const size_t argc = args.GetArgumentCount();
533 case eVarSetOperationClear:
537 case eVarSetOperationReplace:
538 case eVarSetOperationAssign:
539 case eVarSetOperationRemove:
540 case eVarSetOperationInsertBefore:
541 case eVarSetOperationInsertAfter:
542 case eVarSetOperationAppend:
543 case eVarSetOperationInvalid:
544 error = OptionValue::SetValueFromString(value, op);
551 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
552 Stream &strm, uint32_t dump_mask) {
553 const size_t num_properties = m_properties.size();
554 for (size_t i = 0; i < num_properties; ++i) {
555 const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
557 OptionValue *option_value = property->GetValue().get();
558 assert(option_value);
559 const bool transparent_value = option_value->ValueIsTransparent();
560 property->Dump(exe_ctx, strm, dump_mask);
561 if (!transparent_value)
567 Error OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
569 llvm::StringRef property_path,
570 uint32_t dump_mask) {
572 const bool will_modify = false;
573 lldb::OptionValueSP value_sp(
574 GetSubValue(exe_ctx, property_path, will_modify, error));
576 if (!value_sp->ValueIsTransparent()) {
577 if (dump_mask & eDumpOptionName)
578 strm.PutCString(property_path);
579 if (dump_mask & ~eDumpOptionName)
582 value_sp->DumpValue(exe_ctx, strm, dump_mask);
587 lldb::OptionValueSP OptionValueProperties::DeepCopy() const {
588 llvm_unreachable("this shouldn't happen");
591 const Property *OptionValueProperties::GetPropertyAtPath(
592 const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const {
593 const Property *property = nullptr;
596 llvm::StringRef sub_name;
598 size_t key_len = name.find_first_of(".[{");
600 if (key_len != llvm::StringRef::npos) {
601 key.SetString(name.take_front(key_len));
602 sub_name = name.drop_front(key_len);
606 property = GetProperty(exe_ctx, will_modify, key);
607 if (sub_name.empty() || !property)
610 if (sub_name[0] == '.') {
611 OptionValueProperties *sub_properties =
612 property->GetValue()->GetAsProperties();
614 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify,
615 sub_name.drop_front());
620 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
621 Stream &strm) const {
622 size_t max_name_len = 0;
623 const size_t num_properties = m_properties.size();
624 for (size_t i = 0; i < num_properties; ++i) {
625 const Property *property = ProtectedGetPropertyAtIndex(i);
627 max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
629 for (size_t i = 0; i < num_properties; ++i) {
630 const Property *property = ProtectedGetPropertyAtIndex(i);
632 property->DumpDescription(interpreter, strm, max_name_len, false);
636 void OptionValueProperties::Apropos(
637 llvm::StringRef keyword,
638 std::vector<const Property *> &matching_properties) const {
639 const size_t num_properties = m_properties.size();
641 for (size_t i = 0; i < num_properties; ++i) {
642 const Property *property = ProtectedGetPropertyAtIndex(i);
644 const OptionValueProperties *properties =
645 property->GetValue()->GetAsProperties();
647 properties->Apropos(keyword, matching_properties);
650 llvm::StringRef name = property->GetName();
651 if (name.contains_lower(keyword))
654 llvm::StringRef desc = property->GetDescription();
655 if (desc.contains_lower(keyword))
659 matching_properties.push_back(property);
666 lldb::OptionValuePropertiesSP
667 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
668 const ConstString &name) {
669 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
670 if (option_value_sp) {
671 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
673 return ov_properties->shared_from_this();
675 return lldb::OptionValuePropertiesSP();