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