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