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