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) : m_name(name) {}
24
GetNumProperties() const25 size_t OptionValueProperties::GetNumProperties() const {
26 return m_properties.size();
27 }
28
Initialize(const PropertyDefinitions & defs)29 void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
30 for (const auto &definition : defs) {
31 Property property(definition);
32 assert(property.IsValid());
33 m_name_to_index.Append(ConstString(property.GetName()), m_properties.size());
34 property.GetValue()->SetParent(shared_from_this());
35 m_properties.push_back(property);
36 }
37 m_name_to_index.Sort();
38 }
39
SetValueChangedCallback(uint32_t property_idx,std::function<void ()> callback)40 void OptionValueProperties::SetValueChangedCallback(
41 uint32_t property_idx, std::function<void()> callback) {
42 Property *property = ProtectedGetPropertyAtIndex(property_idx);
43 if (property)
44 property->SetValueChangedCallback(std::move(callback));
45 }
46
AppendProperty(ConstString name,ConstString desc,bool is_global,const OptionValueSP & value_sp)47 void OptionValueProperties::AppendProperty(ConstString name,
48 ConstString desc,
49 bool is_global,
50 const OptionValueSP &value_sp) {
51 Property property(name, desc, is_global, value_sp);
52 m_name_to_index.Append(name, m_properties.size());
53 m_properties.push_back(property);
54 value_sp->SetParent(shared_from_this());
55 m_name_to_index.Sort();
56 }
57
58 // bool
59 // OptionValueProperties::GetQualifiedName (Stream &strm)
60 //{
61 // bool dumped_something = false;
62 //// lldb::OptionValuePropertiesSP parent_sp(GetParent ());
63 //// if (parent_sp)
64 //// {
65 //// parent_sp->GetQualifiedName (strm);
66 //// strm.PutChar('.');
67 //// dumped_something = true;
68 //// }
69 // if (m_name)
70 // {
71 // strm << m_name;
72 // dumped_something = true;
73 // }
74 // return dumped_something;
75 //}
76 //
77 lldb::OptionValueSP
GetValueForKey(const ExecutionContext * exe_ctx,ConstString key,bool will_modify) const78 OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
79 ConstString key,
80 bool will_modify) const {
81 lldb::OptionValueSP value_sp;
82 size_t idx = m_name_to_index.Find(key, SIZE_MAX);
83 if (idx < m_properties.size())
84 value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
85 return value_sp;
86 }
87
88 lldb::OptionValueSP
GetSubValue(const ExecutionContext * exe_ctx,llvm::StringRef name,bool will_modify,Status & error) const89 OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
90 llvm::StringRef name, bool will_modify,
91 Status &error) const {
92 lldb::OptionValueSP value_sp;
93 if (name.empty())
94 return OptionValueSP();
95
96 llvm::StringRef sub_name;
97 ConstString key;
98 size_t key_len = name.find_first_of(".[{");
99 if (key_len != llvm::StringRef::npos) {
100 key.SetString(name.take_front(key_len));
101 sub_name = name.drop_front(key_len);
102 } else
103 key.SetString(name);
104
105 value_sp = GetValueForKey(exe_ctx, key, will_modify);
106 if (sub_name.empty() || !value_sp)
107 return value_sp;
108
109 switch (sub_name[0]) {
110 case '.': {
111 lldb::OptionValueSP return_val_sp;
112 return_val_sp =
113 value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error);
114 if (!return_val_sp) {
115 if (Properties::IsSettingExperimental(sub_name.drop_front())) {
116 size_t experimental_len =
117 strlen(Properties::GetExperimentalSettingsName());
118 if (sub_name[experimental_len + 1] == '.')
119 return_val_sp = value_sp->GetSubValue(
120 exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error);
121 // It isn't an error if an experimental setting is not present.
122 if (!return_val_sp)
123 error.Clear();
124 }
125 }
126 return return_val_sp;
127 }
128 case '[':
129 // Array or dictionary access for subvalues like: "[12]" -- access
130 // 12th array element "['hello']" -- dictionary access of key named hello
131 return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
132
133 default:
134 value_sp.reset();
135 break;
136 }
137 return value_sp;
138 }
139
SetSubValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef name,llvm::StringRef value)140 Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
141 VarSetOperationType op,
142 llvm::StringRef name,
143 llvm::StringRef value) {
144 Status error;
145 const bool will_modify = true;
146 llvm::SmallVector<llvm::StringRef, 8> components;
147 name.split(components, '.');
148 bool name_contains_experimental = false;
149 for (const auto &part : components)
150 if (Properties::IsSettingExperimental(part))
151 name_contains_experimental = true;
152
153 lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
154 if (value_sp)
155 error = value_sp->SetValueFromString(value, op);
156 else {
157 // Don't set an error if the path contained .experimental. - those are
158 // allowed to be missing and should silently fail.
159 if (!name_contains_experimental && error.AsCString() == nullptr) {
160 error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
161 }
162 }
163 return error;
164 }
165
166 uint32_t
GetPropertyIndex(ConstString name) const167 OptionValueProperties::GetPropertyIndex(ConstString name) const {
168 return m_name_to_index.Find(name, SIZE_MAX);
169 }
170
171 const Property *
GetProperty(const ExecutionContext * exe_ctx,bool will_modify,ConstString name) const172 OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
173 bool will_modify,
174 ConstString name) const {
175 return GetPropertyAtIndex(
176 exe_ctx, will_modify,
177 m_name_to_index.Find(name, SIZE_MAX));
178 }
179
GetPropertyAtIndex(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const180 const Property *OptionValueProperties::GetPropertyAtIndex(
181 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
182 return ProtectedGetPropertyAtIndex(idx);
183 }
184
GetPropertyValueAtIndex(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const185 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
186 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
187 const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx);
188 if (setting)
189 return setting->GetValue();
190 return OptionValueSP();
191 }
192
193 OptionValuePathMappings *
GetPropertyAtIndexAsOptionValuePathMappings(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const194 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
195 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
196 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
197 if (value_sp)
198 return value_sp->GetAsPathMappings();
199 return nullptr;
200 }
201
202 OptionValueFileSpecList *
GetPropertyAtIndexAsOptionValueFileSpecList(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const203 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
204 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
205 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
206 if (value_sp)
207 return value_sp->GetAsFileSpecList();
208 return nullptr;
209 }
210
GetPropertyAtIndexAsOptionValueArch(const ExecutionContext * exe_ctx,uint32_t idx) const211 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
212 const ExecutionContext *exe_ctx, uint32_t idx) const {
213 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
214 if (property)
215 return property->GetValue()->GetAsArch();
216 return nullptr;
217 }
218
219 OptionValueLanguage *
GetPropertyAtIndexAsOptionValueLanguage(const ExecutionContext * exe_ctx,uint32_t idx) const220 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
221 const ExecutionContext *exe_ctx, uint32_t idx) const {
222 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
223 if (property)
224 return property->GetValue()->GetAsLanguage();
225 return nullptr;
226 }
227
GetPropertyAtIndexAsArgs(const ExecutionContext * exe_ctx,uint32_t idx,Args & args) const228 bool OptionValueProperties::GetPropertyAtIndexAsArgs(
229 const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
230 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
231 if (!property)
232 return false;
233
234 OptionValue *value = property->GetValue().get();
235 if (!value)
236 return false;
237
238 const OptionValueArgs *arguments = value->GetAsArgs();
239 if (arguments)
240 return arguments->GetArgs(args);
241
242 const OptionValueArray *array = value->GetAsArray();
243 if (array)
244 return array->GetArgs(args);
245
246 const OptionValueDictionary *dict = value->GetAsDictionary();
247 if (dict)
248 return dict->GetArgs(args);
249
250 return false;
251 }
252
SetPropertyAtIndexFromArgs(const ExecutionContext * exe_ctx,uint32_t idx,const Args & args)253 bool OptionValueProperties::SetPropertyAtIndexFromArgs(
254 const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
255 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
256 if (!property)
257 return false;
258
259 OptionValue *value = property->GetValue().get();
260 if (!value)
261 return false;
262
263 OptionValueArgs *arguments = value->GetAsArgs();
264 if (arguments)
265 return arguments->SetArgs(args, eVarSetOperationAssign).Success();
266
267 OptionValueArray *array = value->GetAsArray();
268 if (array)
269 return array->SetArgs(args, eVarSetOperationAssign).Success();
270
271 OptionValueDictionary *dict = value->GetAsDictionary();
272 if (dict)
273 return dict->SetArgs(args, eVarSetOperationAssign).Success();
274
275 return false;
276 }
277
GetPropertyAtIndexAsBoolean(const ExecutionContext * exe_ctx,uint32_t idx,bool fail_value) const278 bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
279 const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
280 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
281 if (property) {
282 OptionValue *value = property->GetValue().get();
283 if (value)
284 return value->GetBooleanValue(fail_value);
285 }
286 return fail_value;
287 }
288
SetPropertyAtIndexAsBoolean(const ExecutionContext * exe_ctx,uint32_t idx,bool new_value)289 bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
290 const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
291 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
292 if (property) {
293 OptionValue *value = property->GetValue().get();
294 if (value) {
295 value->SetBooleanValue(new_value);
296 return true;
297 }
298 }
299 return false;
300 }
301
302 OptionValueDictionary *
GetPropertyAtIndexAsOptionValueDictionary(const ExecutionContext * exe_ctx,uint32_t idx) const303 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
304 const ExecutionContext *exe_ctx, uint32_t idx) const {
305 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
306 if (property)
307 return property->GetValue()->GetAsDictionary();
308 return nullptr;
309 }
310
GetPropertyAtIndexAsEnumeration(const ExecutionContext * exe_ctx,uint32_t idx,int64_t fail_value) const311 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
312 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
313 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
314 if (property) {
315 OptionValue *value = property->GetValue().get();
316 if (value)
317 return value->GetEnumerationValue(fail_value);
318 }
319 return fail_value;
320 }
321
SetPropertyAtIndexAsEnumeration(const ExecutionContext * exe_ctx,uint32_t idx,int64_t new_value)322 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
323 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
324 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
325 if (property) {
326 OptionValue *value = property->GetValue().get();
327 if (value)
328 return value->SetEnumerationValue(new_value);
329 }
330 return false;
331 }
332
333 const FormatEntity::Entry *
GetPropertyAtIndexAsFormatEntity(const ExecutionContext * exe_ctx,uint32_t idx)334 OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
335 const ExecutionContext *exe_ctx, uint32_t idx) {
336 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
337 if (property) {
338 OptionValue *value = property->GetValue().get();
339 if (value)
340 return value->GetFormatEntity();
341 }
342 return nullptr;
343 }
344
345 OptionValueFileSpec *
GetPropertyAtIndexAsOptionValueFileSpec(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const346 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
347 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
348 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
349 if (property) {
350 OptionValue *value = property->GetValue().get();
351 if (value)
352 return value->GetAsFileSpec();
353 }
354 return nullptr;
355 }
356
GetPropertyAtIndexAsFileSpec(const ExecutionContext * exe_ctx,uint32_t idx) const357 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
358 const ExecutionContext *exe_ctx, uint32_t idx) const {
359 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
360 if (property) {
361 OptionValue *value = property->GetValue().get();
362 if (value)
363 return value->GetFileSpecValue();
364 }
365 return FileSpec();
366 }
367
SetPropertyAtIndexAsFileSpec(const ExecutionContext * exe_ctx,uint32_t idx,const FileSpec & new_file_spec)368 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
369 const ExecutionContext *exe_ctx, uint32_t idx,
370 const FileSpec &new_file_spec) {
371 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
372 if (property) {
373 OptionValue *value = property->GetValue().get();
374 if (value)
375 return value->SetFileSpecValue(new_file_spec);
376 }
377 return false;
378 }
379
380 const RegularExpression *
GetPropertyAtIndexAsOptionValueRegex(const ExecutionContext * exe_ctx,uint32_t idx) const381 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
382 const ExecutionContext *exe_ctx, uint32_t idx) const {
383 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
384 if (property) {
385 OptionValue *value = property->GetValue().get();
386 if (value)
387 return value->GetRegexValue();
388 }
389 return nullptr;
390 }
391
GetPropertyAtIndexAsOptionValueSInt64(const ExecutionContext * exe_ctx,uint32_t idx) const392 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
393 const ExecutionContext *exe_ctx, uint32_t idx) const {
394 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
395 if (property) {
396 OptionValue *value = property->GetValue().get();
397 if (value)
398 return value->GetAsSInt64();
399 }
400 return nullptr;
401 }
402
GetPropertyAtIndexAsSInt64(const ExecutionContext * exe_ctx,uint32_t idx,int64_t fail_value) const403 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
404 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
405 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
406 if (property) {
407 OptionValue *value = property->GetValue().get();
408 if (value)
409 return value->GetSInt64Value(fail_value);
410 }
411 return fail_value;
412 }
413
SetPropertyAtIndexAsSInt64(const ExecutionContext * exe_ctx,uint32_t idx,int64_t new_value)414 bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
415 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
416 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
417 if (property) {
418 OptionValue *value = property->GetValue().get();
419 if (value)
420 return value->SetSInt64Value(new_value);
421 }
422 return false;
423 }
424
GetPropertyAtIndexAsString(const ExecutionContext * exe_ctx,uint32_t idx,llvm::StringRef fail_value) const425 llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
426 const ExecutionContext *exe_ctx, uint32_t idx,
427 llvm::StringRef fail_value) const {
428 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
429 if (property) {
430 OptionValue *value = property->GetValue().get();
431 if (value)
432 return value->GetStringValue(fail_value);
433 }
434 return fail_value;
435 }
436
SetPropertyAtIndexAsString(const ExecutionContext * exe_ctx,uint32_t idx,llvm::StringRef new_value)437 bool OptionValueProperties::SetPropertyAtIndexAsString(
438 const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
439 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
440 if (property) {
441 OptionValue *value = property->GetValue().get();
442 if (value)
443 return value->SetStringValue(new_value);
444 }
445 return false;
446 }
447
GetPropertyAtIndexAsOptionValueString(const ExecutionContext * exe_ctx,bool will_modify,uint32_t idx) const448 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
449 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
450 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
451 if (value_sp)
452 return value_sp->GetAsString();
453 return nullptr;
454 }
455
GetPropertyAtIndexAsUInt64(const ExecutionContext * exe_ctx,uint32_t idx,uint64_t fail_value) const456 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
457 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
458 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
459 if (property) {
460 OptionValue *value = property->GetValue().get();
461 if (value)
462 return value->GetUInt64Value(fail_value);
463 }
464 return fail_value;
465 }
466
SetPropertyAtIndexAsUInt64(const ExecutionContext * exe_ctx,uint32_t idx,uint64_t new_value)467 bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
468 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
469 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
470 if (property) {
471 OptionValue *value = property->GetValue().get();
472 if (value)
473 return value->SetUInt64Value(new_value);
474 }
475 return false;
476 }
477
Clear()478 void OptionValueProperties::Clear() {
479 const size_t num_properties = m_properties.size();
480 for (size_t i = 0; i < num_properties; ++i)
481 m_properties[i].GetValue()->Clear();
482 }
483
SetValueFromString(llvm::StringRef value,VarSetOperationType op)484 Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
485 VarSetOperationType op) {
486 Status error;
487
488 // Args args(value_cstr);
489 // const size_t argc = args.GetArgumentCount();
490 switch (op) {
491 case eVarSetOperationClear:
492 Clear();
493 break;
494
495 case eVarSetOperationReplace:
496 case eVarSetOperationAssign:
497 case eVarSetOperationRemove:
498 case eVarSetOperationInsertBefore:
499 case eVarSetOperationInsertAfter:
500 case eVarSetOperationAppend:
501 case eVarSetOperationInvalid:
502 error = OptionValue::SetValueFromString(value, op);
503 break;
504 }
505
506 return error;
507 }
508
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)509 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
510 Stream &strm, uint32_t dump_mask) {
511 const size_t num_properties = m_properties.size();
512 for (size_t i = 0; i < num_properties; ++i) {
513 const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
514 if (property) {
515 OptionValue *option_value = property->GetValue().get();
516 assert(option_value);
517 const bool transparent_value = option_value->ValueIsTransparent();
518 property->Dump(exe_ctx, strm, dump_mask);
519 if (!transparent_value)
520 strm.EOL();
521 }
522 }
523 }
524
DumpPropertyValue(const ExecutionContext * exe_ctx,Stream & strm,llvm::StringRef property_path,uint32_t dump_mask)525 Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
526 Stream &strm,
527 llvm::StringRef property_path,
528 uint32_t dump_mask) {
529 Status error;
530 const bool will_modify = false;
531 lldb::OptionValueSP value_sp(
532 GetSubValue(exe_ctx, property_path, will_modify, error));
533 if (value_sp) {
534 if (!value_sp->ValueIsTransparent()) {
535 if (dump_mask & eDumpOptionName)
536 strm.PutCString(property_path);
537 if (dump_mask & ~eDumpOptionName)
538 strm.PutChar(' ');
539 }
540 value_sp->DumpValue(exe_ctx, strm, dump_mask);
541 }
542 return error;
543 }
544
545 OptionValuePropertiesSP
CreateLocalCopy(const Properties & global_properties)546 OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {
547 auto global_props_sp = global_properties.GetValueProperties();
548 lldbassert(global_props_sp);
549
550 auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
551 return std::static_pointer_cast<OptionValueProperties>(copy_sp);
552 }
553
554 OptionValueSP
DeepCopy(const OptionValueSP & new_parent) const555 OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {
556 auto copy_sp = OptionValue::DeepCopy(new_parent);
557 // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
558 // types that override GetType returning a different value.
559 auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
560 lldbassert(props_value_ptr);
561
562 for (auto &property : props_value_ptr->m_properties) {
563 // Duplicate any values that are not global when constructing properties
564 // from a global copy.
565 if (!property.IsGlobal()) {
566 auto value_sp = property.GetValue()->DeepCopy(copy_sp);
567 property.SetOptionValue(value_sp);
568 }
569 }
570 return copy_sp;
571 }
572
GetPropertyAtPath(const ExecutionContext * exe_ctx,bool will_modify,llvm::StringRef name) const573 const Property *OptionValueProperties::GetPropertyAtPath(
574 const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const {
575 const Property *property = nullptr;
576 if (name.empty())
577 return nullptr;
578 llvm::StringRef sub_name;
579 ConstString key;
580 size_t key_len = name.find_first_of(".[{");
581
582 if (key_len != llvm::StringRef::npos) {
583 key.SetString(name.take_front(key_len));
584 sub_name = name.drop_front(key_len);
585 } else
586 key.SetString(name);
587
588 property = GetProperty(exe_ctx, will_modify, key);
589 if (sub_name.empty() || !property)
590 return property;
591
592 if (sub_name[0] == '.') {
593 OptionValueProperties *sub_properties =
594 property->GetValue()->GetAsProperties();
595 if (sub_properties)
596 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify,
597 sub_name.drop_front());
598 }
599 return nullptr;
600 }
601
DumpAllDescriptions(CommandInterpreter & interpreter,Stream & strm) const602 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
603 Stream &strm) const {
604 size_t max_name_len = 0;
605 const size_t num_properties = m_properties.size();
606 for (size_t i = 0; i < num_properties; ++i) {
607 const Property *property = ProtectedGetPropertyAtIndex(i);
608 if (property)
609 max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
610 }
611 for (size_t i = 0; i < num_properties; ++i) {
612 const Property *property = ProtectedGetPropertyAtIndex(i);
613 if (property)
614 property->DumpDescription(interpreter, strm, max_name_len, false);
615 }
616 }
617
Apropos(llvm::StringRef keyword,std::vector<const Property * > & matching_properties) const618 void OptionValueProperties::Apropos(
619 llvm::StringRef keyword,
620 std::vector<const Property *> &matching_properties) const {
621 const size_t num_properties = m_properties.size();
622 StreamString strm;
623 for (size_t i = 0; i < num_properties; ++i) {
624 const Property *property = ProtectedGetPropertyAtIndex(i);
625 if (property) {
626 const OptionValueProperties *properties =
627 property->GetValue()->GetAsProperties();
628 if (properties) {
629 properties->Apropos(keyword, matching_properties);
630 } else {
631 bool match = false;
632 llvm::StringRef name = property->GetName();
633 if (name.contains_insensitive(keyword))
634 match = true;
635 else {
636 llvm::StringRef desc = property->GetDescription();
637 if (desc.contains_insensitive(keyword))
638 match = true;
639 }
640 if (match) {
641 matching_properties.push_back(property);
642 }
643 }
644 }
645 }
646 }
647
648 lldb::OptionValuePropertiesSP
GetSubProperty(const ExecutionContext * exe_ctx,ConstString name)649 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
650 ConstString name) {
651 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
652 if (option_value_sp) {
653 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
654 if (ov_properties)
655 return ov_properties->shared_from_this();
656 }
657 return lldb::OptionValuePropertiesSP();
658 }
659