1 //===-- OptionValueProperties.cpp -----------------------------------------===//
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 // Array or dictionary access for subvalues like: "[12]" -- access
152 // 12th array element "['hello']" -- dictionary access of key named hello
153 return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
154
155 default:
156 value_sp.reset();
157 break;
158 }
159 return value_sp;
160 }
161
SetSubValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef name,llvm::StringRef value)162 Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
163 VarSetOperationType op,
164 llvm::StringRef name,
165 llvm::StringRef value) {
166 Status error;
167 const bool will_modify = true;
168 llvm::SmallVector<llvm::StringRef, 8> components;
169 name.split(components, '.');
170 bool name_contains_experimental = false;
171 for (const auto &part : components)
172 if (Properties::IsSettingExperimental(part))
173 name_contains_experimental = true;
174
175 lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
176 if (value_sp)
177 error = value_sp->SetValueFromString(value, op);
178 else {
179 // Don't set an error if the path contained .experimental. - those are
180 // allowed to be missing and should silently fail.
181 if (!name_contains_experimental && error.AsCString() == nullptr) {
182 error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
183 }
184 }
185 return error;
186 }
187
188 uint32_t
GetPropertyIndex(ConstString name) const189 OptionValueProperties::GetPropertyIndex(ConstString name) const {
190 return m_name_to_index.Find(name, SIZE_MAX);
191 }
192
193 const Property *
GetProperty(const ExecutionContext * exe_ctx,bool will_modify,ConstString name) const194 OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
195 bool will_modify,
196 ConstString name) const {
197 return GetPropertyAtIndex(
198 exe_ctx, will_modify,
199 m_name_to_index.Find(name, SIZE_MAX));
200 }
201
GetPropertyAtIndex(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const202 const Property *OptionValueProperties::GetPropertyAtIndex(
203 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
204 return ProtectedGetPropertyAtIndex(idx);
205 }
206
GetPropertyValueAtIndex(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const207 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
208 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
209 const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx);
210 if (setting)
211 return setting->GetValue();
212 return OptionValueSP();
213 }
214
215 OptionValuePathMappings *
GetPropertyAtIndexAsOptionValuePathMappings(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const216 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
217 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
218 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
219 if (value_sp)
220 return value_sp->GetAsPathMappings();
221 return nullptr;
222 }
223
224 OptionValueFileSpecList *
GetPropertyAtIndexAsOptionValueFileSpecList(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const225 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
226 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
227 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
228 if (value_sp)
229 return value_sp->GetAsFileSpecList();
230 return nullptr;
231 }
232
GetPropertyAtIndexAsOptionValueArch(const ExecutionContext * exe_ctx,uint32_t idx) const233 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
234 const ExecutionContext *exe_ctx, uint32_t idx) const {
235 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
236 if (property)
237 return property->GetValue()->GetAsArch();
238 return nullptr;
239 }
240
241 OptionValueLanguage *
GetPropertyAtIndexAsOptionValueLanguage(const ExecutionContext * exe_ctx,uint32_t idx) const242 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
243 const ExecutionContext *exe_ctx, uint32_t idx) const {
244 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
245 if (property)
246 return property->GetValue()->GetAsLanguage();
247 return nullptr;
248 }
249
GetPropertyAtIndexAsArgs(const ExecutionContext * exe_ctx,uint32_t idx,Args & args) const250 bool OptionValueProperties::GetPropertyAtIndexAsArgs(
251 const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
252 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
253 if (property) {
254 OptionValue *value = property->GetValue().get();
255 if (value) {
256 const OptionValueArray *array = value->GetAsArray();
257 if (array)
258 return array->GetArgs(args);
259 else {
260 const OptionValueDictionary *dict = value->GetAsDictionary();
261 if (dict)
262 return dict->GetArgs(args);
263 }
264 }
265 }
266 return false;
267 }
268
SetPropertyAtIndexFromArgs(const ExecutionContext * exe_ctx,uint32_t idx,const Args & args)269 bool OptionValueProperties::SetPropertyAtIndexFromArgs(
270 const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
271 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
272 if (property) {
273 OptionValue *value = property->GetValue().get();
274 if (value) {
275 OptionValueArray *array = value->GetAsArray();
276 if (array)
277 return array->SetArgs(args, eVarSetOperationAssign).Success();
278 else {
279 OptionValueDictionary *dict = value->GetAsDictionary();
280 if (dict)
281 return dict->SetArgs(args, eVarSetOperationAssign).Success();
282 }
283 }
284 }
285 return false;
286 }
287
GetPropertyAtIndexAsBoolean(const ExecutionContext * exe_ctx,uint32_t idx,bool fail_value) const288 bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
289 const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
290 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
291 if (property) {
292 OptionValue *value = property->GetValue().get();
293 if (value)
294 return value->GetBooleanValue(fail_value);
295 }
296 return fail_value;
297 }
298
SetPropertyAtIndexAsBoolean(const ExecutionContext * exe_ctx,uint32_t idx,bool new_value)299 bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
300 const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
301 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
302 if (property) {
303 OptionValue *value = property->GetValue().get();
304 if (value) {
305 value->SetBooleanValue(new_value);
306 return true;
307 }
308 }
309 return false;
310 }
311
312 OptionValueDictionary *
GetPropertyAtIndexAsOptionValueDictionary(const ExecutionContext * exe_ctx,uint32_t idx) const313 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
314 const ExecutionContext *exe_ctx, uint32_t idx) const {
315 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
316 if (property)
317 return property->GetValue()->GetAsDictionary();
318 return nullptr;
319 }
320
GetPropertyAtIndexAsEnumeration(const ExecutionContext * exe_ctx,uint32_t idx,int64_t fail_value) const321 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
322 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
323 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
324 if (property) {
325 OptionValue *value = property->GetValue().get();
326 if (value)
327 return value->GetEnumerationValue(fail_value);
328 }
329 return fail_value;
330 }
331
SetPropertyAtIndexAsEnumeration(const ExecutionContext * exe_ctx,uint32_t idx,int64_t new_value)332 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
333 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
334 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
335 if (property) {
336 OptionValue *value = property->GetValue().get();
337 if (value)
338 return value->SetEnumerationValue(new_value);
339 }
340 return false;
341 }
342
343 const FormatEntity::Entry *
GetPropertyAtIndexAsFormatEntity(const ExecutionContext * exe_ctx,uint32_t idx)344 OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
345 const ExecutionContext *exe_ctx, uint32_t idx) {
346 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
347 if (property) {
348 OptionValue *value = property->GetValue().get();
349 if (value)
350 return value->GetFormatEntity();
351 }
352 return nullptr;
353 }
354
355 OptionValueFileSpec *
GetPropertyAtIndexAsOptionValueFileSpec(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const356 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
357 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
358 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
359 if (property) {
360 OptionValue *value = property->GetValue().get();
361 if (value)
362 return value->GetAsFileSpec();
363 }
364 return nullptr;
365 }
366
GetPropertyAtIndexAsFileSpec(const ExecutionContext * exe_ctx,uint32_t idx) const367 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
368 const ExecutionContext *exe_ctx, uint32_t idx) const {
369 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
370 if (property) {
371 OptionValue *value = property->GetValue().get();
372 if (value)
373 return value->GetFileSpecValue();
374 }
375 return FileSpec();
376 }
377
SetPropertyAtIndexAsFileSpec(const ExecutionContext * exe_ctx,uint32_t idx,const FileSpec & new_file_spec)378 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
379 const ExecutionContext *exe_ctx, uint32_t idx,
380 const FileSpec &new_file_spec) {
381 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
382 if (property) {
383 OptionValue *value = property->GetValue().get();
384 if (value)
385 return value->SetFileSpecValue(new_file_spec);
386 }
387 return false;
388 }
389
390 const RegularExpression *
GetPropertyAtIndexAsOptionValueRegex(const ExecutionContext * exe_ctx,uint32_t idx) const391 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
392 const ExecutionContext *exe_ctx, uint32_t idx) const {
393 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
394 if (property) {
395 OptionValue *value = property->GetValue().get();
396 if (value)
397 return value->GetRegexValue();
398 }
399 return nullptr;
400 }
401
GetPropertyAtIndexAsOptionValueSInt64(const ExecutionContext * exe_ctx,uint32_t idx) const402 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
403 const ExecutionContext *exe_ctx, uint32_t idx) const {
404 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
405 if (property) {
406 OptionValue *value = property->GetValue().get();
407 if (value)
408 return value->GetAsSInt64();
409 }
410 return nullptr;
411 }
412
GetPropertyAtIndexAsSInt64(const ExecutionContext * exe_ctx,uint32_t idx,int64_t fail_value) const413 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
414 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
415 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
416 if (property) {
417 OptionValue *value = property->GetValue().get();
418 if (value)
419 return value->GetSInt64Value(fail_value);
420 }
421 return fail_value;
422 }
423
SetPropertyAtIndexAsSInt64(const ExecutionContext * exe_ctx,uint32_t idx,int64_t new_value)424 bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
425 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
426 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
427 if (property) {
428 OptionValue *value = property->GetValue().get();
429 if (value)
430 return value->SetSInt64Value(new_value);
431 }
432 return false;
433 }
434
GetPropertyAtIndexAsString(const ExecutionContext * exe_ctx,uint32_t idx,llvm::StringRef fail_value) const435 llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
436 const ExecutionContext *exe_ctx, uint32_t idx,
437 llvm::StringRef fail_value) 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->GetStringValue(fail_value);
443 }
444 return fail_value;
445 }
446
SetPropertyAtIndexAsString(const ExecutionContext * exe_ctx,uint32_t idx,llvm::StringRef new_value)447 bool OptionValueProperties::SetPropertyAtIndexAsString(
448 const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
449 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
450 if (property) {
451 OptionValue *value = property->GetValue().get();
452 if (value)
453 return value->SetStringValue(new_value);
454 }
455 return false;
456 }
457
GetPropertyAtIndexAsOptionValueString(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const458 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
459 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
460 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
461 if (value_sp)
462 return value_sp->GetAsString();
463 return nullptr;
464 }
465
GetPropertyAtIndexAsUInt64(const ExecutionContext * exe_ctx,uint32_t idx,uint64_t fail_value) const466 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
467 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
468 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
469 if (property) {
470 OptionValue *value = property->GetValue().get();
471 if (value)
472 return value->GetUInt64Value(fail_value);
473 }
474 return fail_value;
475 }
476
SetPropertyAtIndexAsUInt64(const ExecutionContext * exe_ctx,uint32_t idx,uint64_t new_value)477 bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
478 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
479 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
480 if (property) {
481 OptionValue *value = property->GetValue().get();
482 if (value)
483 return value->SetUInt64Value(new_value);
484 }
485 return false;
486 }
487
Clear()488 void OptionValueProperties::Clear() {
489 const size_t num_properties = m_properties.size();
490 for (size_t i = 0; i < num_properties; ++i)
491 m_properties[i].GetValue()->Clear();
492 }
493
SetValueFromString(llvm::StringRef value,VarSetOperationType op)494 Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
495 VarSetOperationType op) {
496 Status error;
497
498 // Args args(value_cstr);
499 // const size_t argc = args.GetArgumentCount();
500 switch (op) {
501 case eVarSetOperationClear:
502 Clear();
503 break;
504
505 case eVarSetOperationReplace:
506 case eVarSetOperationAssign:
507 case eVarSetOperationRemove:
508 case eVarSetOperationInsertBefore:
509 case eVarSetOperationInsertAfter:
510 case eVarSetOperationAppend:
511 case eVarSetOperationInvalid:
512 error = OptionValue::SetValueFromString(value, op);
513 break;
514 }
515
516 return error;
517 }
518
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)519 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
520 Stream &strm, uint32_t dump_mask) {
521 const size_t num_properties = m_properties.size();
522 for (size_t i = 0; i < num_properties; ++i) {
523 const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
524 if (property) {
525 OptionValue *option_value = property->GetValue().get();
526 assert(option_value);
527 const bool transparent_value = option_value->ValueIsTransparent();
528 property->Dump(exe_ctx, strm, dump_mask);
529 if (!transparent_value)
530 strm.EOL();
531 }
532 }
533 }
534
DumpPropertyValue(const ExecutionContext * exe_ctx,Stream & strm,llvm::StringRef property_path,uint32_t dump_mask)535 Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
536 Stream &strm,
537 llvm::StringRef property_path,
538 uint32_t dump_mask) {
539 Status error;
540 const bool will_modify = false;
541 lldb::OptionValueSP value_sp(
542 GetSubValue(exe_ctx, property_path, will_modify, error));
543 if (value_sp) {
544 if (!value_sp->ValueIsTransparent()) {
545 if (dump_mask & eDumpOptionName)
546 strm.PutCString(property_path);
547 if (dump_mask & ~eDumpOptionName)
548 strm.PutChar(' ');
549 }
550 value_sp->DumpValue(exe_ctx, strm, dump_mask);
551 }
552 return error;
553 }
554
DeepCopy() const555 lldb::OptionValueSP OptionValueProperties::DeepCopy() const {
556 llvm_unreachable("this shouldn't happen");
557 }
558
GetPropertyAtPath(const ExecutionContext * exe_ctx,bool will_modify,llvm::StringRef name) const559 const Property *OptionValueProperties::GetPropertyAtPath(
560 const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const {
561 const Property *property = nullptr;
562 if (name.empty())
563 return nullptr;
564 llvm::StringRef sub_name;
565 ConstString key;
566 size_t key_len = name.find_first_of(".[{");
567
568 if (key_len != llvm::StringRef::npos) {
569 key.SetString(name.take_front(key_len));
570 sub_name = name.drop_front(key_len);
571 } else
572 key.SetString(name);
573
574 property = GetProperty(exe_ctx, will_modify, key);
575 if (sub_name.empty() || !property)
576 return property;
577
578 if (sub_name[0] == '.') {
579 OptionValueProperties *sub_properties =
580 property->GetValue()->GetAsProperties();
581 if (sub_properties)
582 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify,
583 sub_name.drop_front());
584 }
585 return nullptr;
586 }
587
DumpAllDescriptions(CommandInterpreter & interpreter,Stream & strm) const588 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
589 Stream &strm) const {
590 size_t max_name_len = 0;
591 const size_t num_properties = m_properties.size();
592 for (size_t i = 0; i < num_properties; ++i) {
593 const Property *property = ProtectedGetPropertyAtIndex(i);
594 if (property)
595 max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
596 }
597 for (size_t i = 0; i < num_properties; ++i) {
598 const Property *property = ProtectedGetPropertyAtIndex(i);
599 if (property)
600 property->DumpDescription(interpreter, strm, max_name_len, false);
601 }
602 }
603
Apropos(llvm::StringRef keyword,std::vector<const Property * > & matching_properties) const604 void OptionValueProperties::Apropos(
605 llvm::StringRef keyword,
606 std::vector<const Property *> &matching_properties) const {
607 const size_t num_properties = m_properties.size();
608 StreamString strm;
609 for (size_t i = 0; i < num_properties; ++i) {
610 const Property *property = ProtectedGetPropertyAtIndex(i);
611 if (property) {
612 const OptionValueProperties *properties =
613 property->GetValue()->GetAsProperties();
614 if (properties) {
615 properties->Apropos(keyword, matching_properties);
616 } else {
617 bool match = false;
618 llvm::StringRef name = property->GetName();
619 if (name.contains_lower(keyword))
620 match = true;
621 else {
622 llvm::StringRef desc = property->GetDescription();
623 if (desc.contains_lower(keyword))
624 match = true;
625 }
626 if (match) {
627 matching_properties.push_back(property);
628 }
629 }
630 }
631 }
632 }
633
634 lldb::OptionValuePropertiesSP
GetSubProperty(const ExecutionContext * exe_ctx,ConstString name)635 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
636 ConstString name) {
637 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
638 if (option_value_sp) {
639 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
640 if (ov_properties)
641 return ov_properties->shared_from_this();
642 }
643 return lldb::OptionValuePropertiesSP();
644 }
645