LLDB mainline
OptionValueProperties.cpp
Go to the documentation of this file.
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
10
11#include "lldb/Utility/Flags.h"
12
16#include "lldb/Utility/Args.h"
17#include "lldb/Utility/Stream.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
24 : m_name(name.str()) {}
25
27 for (const auto &definition : defs) {
28 Property property(definition);
29 assert(property.IsValid());
30 m_name_to_index.insert({property.GetName(), m_properties.size()});
31 property.GetValue()->SetParent(shared_from_this());
32 m_properties.push_back(property);
33 }
34}
35
37 size_t property_idx, std::function<void()> callback) {
38 Property *property = ProtectedGetPropertyAtIndex(property_idx);
39 if (property)
40 property->SetValueChangedCallback(std::move(callback));
41}
42
43void OptionValueProperties::AppendProperty(llvm::StringRef name,
44 llvm::StringRef desc, bool is_global,
45 const OptionValueSP &value_sp) {
46 Property property(name, desc, is_global, value_sp);
47 m_name_to_index.insert({name, m_properties.size()});
48 m_properties.push_back(property);
49 value_sp->SetParent(shared_from_this());
50}
51
54 llvm::StringRef key) const {
55 auto iter = m_name_to_index.find(key);
56 if (iter == m_name_to_index.end())
57 return OptionValueSP();
58 const size_t idx = iter->second;
59 if (idx >= m_properties.size())
60 return OptionValueSP();
61 return GetPropertyAtIndex(idx, exe_ctx)->GetValue();
62}
63
66 llvm::StringRef name, Status &error) const {
67 lldb::OptionValueSP value_sp;
68 if (name.empty())
69 return OptionValueSP();
70
71 llvm::StringRef sub_name;
72 llvm::StringRef key;
73 size_t key_len = name.find_first_of(".[{");
74 if (key_len != llvm::StringRef::npos) {
75 key = name.take_front(key_len);
76 sub_name = name.drop_front(key_len);
77 } else
78 key = name;
79
80 value_sp = GetValueForKey(exe_ctx, key);
81 if (sub_name.empty() || !value_sp)
82 return value_sp;
83
84 switch (sub_name[0]) {
85 case '.': {
86 lldb::OptionValueSP return_val_sp;
87 return_val_sp =
88 value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), error);
89 if (!return_val_sp) {
90 if (Properties::IsSettingExperimental(sub_name.drop_front())) {
91 const size_t experimental_len =
93 if (sub_name[experimental_len + 1] == '.')
94 return_val_sp = value_sp->GetSubValue(
95 exe_ctx, sub_name.drop_front(experimental_len + 2), error);
96 // It isn't an error if an experimental setting is not present.
97 if (!return_val_sp)
98 error.Clear();
99 }
100 }
101 return return_val_sp;
102 }
103 case '[':
104 // Array or dictionary access for subvalues like: "[12]" -- access
105 // 12th array element "['hello']" -- dictionary access of key named hello
106 return value_sp->GetSubValue(exe_ctx, sub_name, error);
107
108 default:
109 value_sp.reset();
110 break;
111 }
112 return value_sp;
113}
114
117 llvm::StringRef name,
118 llvm::StringRef value) {
120 llvm::SmallVector<llvm::StringRef, 8> components;
121 name.split(components, '.');
122 bool name_contains_experimental = false;
123 for (const auto &part : components)
125 name_contains_experimental = true;
126
127 lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, error));
128 if (value_sp)
129 error = value_sp->SetValueFromString(value, op);
130 else {
131 // Don't set an error if the path contained .experimental. - those are
132 // allowed to be missing and should silently fail.
133 if (!name_contains_experimental && error.AsCString() == nullptr) {
134 error.SetErrorStringWithFormat("invalid value path '%s'",
135 name.str().c_str());
136 }
137 }
138 return error;
139}
140
141size_t OptionValueProperties::GetPropertyIndex(llvm::StringRef name) const {
142 auto iter = m_name_to_index.find(name);
143 if (iter == m_name_to_index.end())
144 return SIZE_MAX;
145 return iter->second;
146}
147
148const Property *
150 const ExecutionContext *exe_ctx) const {
151 auto iter = m_name_to_index.find(name);
152 if (iter == m_name_to_index.end())
153 return nullptr;
154 return GetPropertyAtIndex(iter->second, exe_ctx);
155}
156
158 size_t idx, const ExecutionContext *exe_ctx) const {
159 const Property *setting = GetPropertyAtIndex(idx, exe_ctx);
160 if (setting)
161 return setting->GetValue();
162 return OptionValueSP();
163}
164
167 size_t idx, const ExecutionContext *exe_ctx) const {
168 OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
169 if (value_sp)
170 return value_sp->GetAsPathMappings();
171 return nullptr;
172}
173
176 size_t idx, const ExecutionContext *exe_ctx) const {
177 OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
178 if (value_sp)
179 return value_sp->GetAsFileSpecList();
180 return nullptr;
181}
182
184 size_t idx, Args &args, const ExecutionContext *exe_ctx) const {
185 const Property *property = GetPropertyAtIndex(idx, exe_ctx);
186 if (!property)
187 return false;
188
189 OptionValue *value = property->GetValue().get();
190 if (!value)
191 return false;
192
193 const OptionValueArgs *arguments = value->GetAsArgs();
194 if (arguments) {
195 arguments->GetArgs(args);
196 return true;
197 }
198
199 const OptionValueArray *array = value->GetAsArray();
200 if (array) {
201 array->GetArgs(args);
202 return true;
203 }
204
205 const OptionValueDictionary *dict = value->GetAsDictionary();
206 if (dict) {
207 dict->GetArgs(args);
208 return true;
209 }
210
211 return false;
212}
213
215 size_t idx, const Args &args, const ExecutionContext *exe_ctx) {
216 const Property *property = GetPropertyAtIndex(idx, exe_ctx);
217 if (!property)
218 return false;
219
220 OptionValue *value = property->GetValue().get();
221 if (!value)
222 return false;
223
224 OptionValueArgs *arguments = value->GetAsArgs();
225 if (arguments)
226 return arguments->SetArgs(args, eVarSetOperationAssign).Success();
227
228 OptionValueArray *array = value->GetAsArray();
229 if (array)
230 return array->SetArgs(args, eVarSetOperationAssign).Success();
231
232 OptionValueDictionary *dict = value->GetAsDictionary();
233 if (dict)
234 return dict->SetArgs(args, eVarSetOperationAssign).Success();
235
236 return false;
237}
238
241 size_t idx, const ExecutionContext *exe_ctx) const {
242 const Property *property = GetPropertyAtIndex(idx, exe_ctx);
243 if (property)
244 return property->GetValue()->GetAsDictionary();
245 return nullptr;
246}
247
250 size_t idx, const ExecutionContext *exe_ctx) const {
251 const Property *property = GetPropertyAtIndex(idx, exe_ctx);
252 if (property) {
253 OptionValue *value = property->GetValue().get();
254 if (value)
255 return value->GetAsFileSpec();
256 }
257 return nullptr;
258}
259
261 size_t idx, const ExecutionContext *exe_ctx) const {
262 const Property *property = GetPropertyAtIndex(idx, exe_ctx);
263 if (property) {
264 OptionValue *value = property->GetValue().get();
265 if (value)
266 return value->GetAsSInt64();
267 }
268 return nullptr;
269}
270
272 size_t idx, const ExecutionContext *exe_ctx) const {
273 const Property *property = GetPropertyAtIndex(idx, exe_ctx);
274 if (property) {
275 OptionValue *value = property->GetValue().get();
276 if (value)
277 return value->GetAsUInt64();
278 }
279 return nullptr;
280}
281
283 size_t idx, const ExecutionContext *exe_ctx) const {
284 OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
285 if (value_sp)
286 return value_sp->GetAsString();
287 return nullptr;
288}
289
291 const size_t num_properties = m_properties.size();
292 for (size_t i = 0; i < num_properties; ++i)
293 m_properties[i].GetValue()->Clear();
294}
295
299
300 // Args args(value_cstr);
301 // const size_t argc = args.GetArgumentCount();
302 switch (op) {
304 Clear();
305 break;
306
315 break;
316 }
317
318 return error;
319}
320
322 Stream &strm, uint32_t dump_mask) {
323 const size_t num_properties = m_properties.size();
324 for (size_t i = 0; i < num_properties; ++i) {
325 const Property *property = GetPropertyAtIndex(i, exe_ctx);
326 if (property) {
327 OptionValue *option_value = property->GetValue().get();
328 assert(option_value);
329 const bool transparent_value = option_value->ValueIsTransparent();
330 property->Dump(exe_ctx, strm, dump_mask);
331 if (!transparent_value)
332 strm.EOL();
333 }
334 }
335}
336
337llvm::json::Value
339 llvm::json::Object json_properties;
340 const size_t num_properties = m_properties.size();
341 for (size_t i = 0; i < num_properties; ++i) {
342 const Property *property = GetPropertyAtIndex(i, exe_ctx);
343 if (property) {
344 OptionValue *option_value = property->GetValue().get();
345 assert(option_value);
346 json_properties.try_emplace(property->GetName(),
347 option_value->ToJSON(exe_ctx));
348 }
349 }
350 return json_properties;
351}
352
354 Stream &strm,
355 llvm::StringRef property_path,
356 uint32_t dump_mask,
357 bool is_json) {
359 lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, property_path, error));
360 if (value_sp) {
361 if (!value_sp->ValueIsTransparent()) {
362 if (dump_mask & eDumpOptionName)
363 strm.PutCString(property_path);
364 if (dump_mask & ~eDumpOptionName)
365 strm.PutChar(' ');
366 }
367 if (is_json) {
368 strm.Printf(
369 "%s",
370 llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str());
371 } else
372 value_sp->DumpValue(exe_ctx, strm, dump_mask);
373 }
374 return error;
375}
376
379 auto global_props_sp = global_properties.GetValueProperties();
380 lldbassert(global_props_sp);
381
382 auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
383 return std::static_pointer_cast<OptionValueProperties>(copy_sp);
384}
385
388 auto copy_sp = OptionValue::DeepCopy(new_parent);
389 // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
390 // types that override GetType returning a different value.
391 auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
392 lldbassert(props_value_ptr);
393
394 for (auto &property : props_value_ptr->m_properties) {
395 // Duplicate any values that are not global when constructing properties
396 // from a global copy.
397 if (!property.IsGlobal()) {
398 auto value_sp = property.GetValue()->DeepCopy(copy_sp);
399 property.SetOptionValue(value_sp);
400 }
401 }
402 return copy_sp;
403}
404
405const Property *
407 llvm::StringRef name) const {
408 if (name.empty())
409 return nullptr;
410
411 const Property *property = nullptr;
412 llvm::StringRef sub_name;
413 llvm::StringRef key;
414 size_t key_len = name.find_first_of(".[{");
415
416 if (key_len != llvm::StringRef::npos) {
417 key = name.take_front(key_len);
418 sub_name = name.drop_front(key_len);
419 } else
420 key = name;
421
422 property = GetProperty(key, exe_ctx);
423 if (sub_name.empty() || !property)
424 return property;
425
426 if (sub_name[0] == '.') {
427 OptionValueProperties *sub_properties =
428 property->GetValue()->GetAsProperties();
429 if (sub_properties)
430 return sub_properties->GetPropertyAtPath(exe_ctx, sub_name.drop_front());
431 }
432 return nullptr;
433}
434
436 Stream &strm) const {
437 size_t max_name_len = 0;
438 const size_t num_properties = m_properties.size();
439 for (size_t i = 0; i < num_properties; ++i) {
440 const Property *property = ProtectedGetPropertyAtIndex(i);
441 if (property)
442 max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
443 }
444 for (size_t i = 0; i < num_properties; ++i) {
445 const Property *property = ProtectedGetPropertyAtIndex(i);
446 if (property)
447 property->DumpDescription(interpreter, strm, max_name_len, false);
448 }
449}
450
452 llvm::StringRef keyword,
453 std::vector<const Property *> &matching_properties) const {
454 const size_t num_properties = m_properties.size();
455 StreamString strm;
456 for (size_t i = 0; i < num_properties; ++i) {
457 const Property *property = ProtectedGetPropertyAtIndex(i);
458 if (property) {
459 const OptionValueProperties *properties =
460 property->GetValue()->GetAsProperties();
461 if (properties) {
462 properties->Apropos(keyword, matching_properties);
463 } else {
464 bool match = false;
465 llvm::StringRef name = property->GetName();
466 if (name.contains_insensitive(keyword))
467 match = true;
468 else {
469 llvm::StringRef desc = property->GetDescription();
470 if (desc.contains_insensitive(keyword))
471 match = true;
472 }
473 if (match) {
474 matching_properties.push_back(property);
475 }
476 }
477 }
478 }
479}
480
483 llvm::StringRef name) {
484 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name));
485 if (option_value_sp) {
486 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
487 if (ov_properties)
488 return ov_properties->shared_from_this();
489 }
491}
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition: LLDBAssert.h:15
A command line argument class.
Definition: Args.h:33
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
size_t GetArgs(Args &args) const
Status SetArgs(const Args &args, VarSetOperationType op)
size_t GetArgs(Args &args) const
Status SetArgs(const Args &args, VarSetOperationType op)
void AppendProperty(llvm::StringRef name, llvm::StringRef desc, bool is_global, const lldb::OptionValueSP &value_sp)
llvm::StringMap< size_t > m_name_to_index
Status SetSubValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef path, llvm::StringRef value) override
void Initialize(const PropertyDefinitions &setting_definitions)
OptionValueFileSpec * GetPropertyAtIndexAsOptionValueFileSpec(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
void Apropos(llvm::StringRef keyword, std::vector< const Property * > &matching_properties) const
lldb::OptionValueSP DeepCopy(const lldb::OptionValueSP &new_parent) const override
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override
virtual void DumpAllDescriptions(CommandInterpreter &interpreter, Stream &strm) const
OptionValueFileSpecList * GetPropertyAtIndexAsOptionValueFileSpecList(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
Property * ProtectedGetPropertyAtIndex(size_t idx)
OptionValueString * GetPropertyAtIndexAsOptionValueString(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx, Stream &strm, llvm::StringRef property_path, uint32_t dump_mask, bool is_json=false)
llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override
OptionValueDictionary * GetPropertyAtIndexAsOptionValueDictionary(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
static lldb::OptionValuePropertiesSP CreateLocalCopy(const Properties &global_properties)
lldb::OptionValueSP GetSubValue(const ExecutionContext *exe_ctx, llvm::StringRef name, Status &error) const override
void SetValueChangedCallback(size_t property_idx, std::function< void()> callback)
bool SetPropertyAtIndexFromArgs(size_t idx, const Args &args, const ExecutionContext *exe_ctx=nullptr)
Status SetValueFromString(llvm::StringRef value, VarSetOperationType op=eVarSetOperationAssign) override
virtual const Property * GetPropertyAtPath(const ExecutionContext *exe_ctx, llvm::StringRef property_path) const
virtual const Property * GetPropertyAtIndex(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
virtual lldb::OptionValueSP GetValueForKey(const ExecutionContext *exe_ctx, llvm::StringRef key) const
lldb::OptionValuePropertiesSP GetSubProperty(const ExecutionContext *exe_ctx, llvm::StringRef name)
virtual lldb::OptionValueSP GetPropertyValueAtIndex(size_t idx, const ExecutionContext *exe_ctx) const
OptionValueUInt64 * GetPropertyAtIndexAsOptionValueUInt64(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
OptionValuePathMappings * GetPropertyAtIndexAsOptionValuePathMappings(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
OptionValueSInt64 * GetPropertyAtIndexAsOptionValueSInt64(size_t idx, const ExecutionContext *exe_ctx=nullptr) const
virtual const Property * GetProperty(llvm::StringRef name, const ExecutionContext *exe_ctx=nullptr) const
bool GetPropertyAtIndexAsArgs(size_t idx, Args &args, const ExecutionContext *exe_ctx=nullptr) const
virtual size_t GetPropertyIndex(llvm::StringRef name) const
OptionValueDictionary * GetAsDictionary()
virtual Status SetValueFromString(llvm::StringRef value, VarSetOperationType op=eVarSetOperationAssign)
OptionValueSInt64 * GetAsSInt64()
virtual llvm::json::Value ToJSON(const ExecutionContext *exe_ctx)
Definition: OptionValue.h:98
virtual bool ValueIsTransparent() const
Definition: OptionValue.h:83
OptionValueUInt64 * GetAsUInt64()
OptionValueProperties * GetAsProperties()
virtual lldb::OptionValueSP DeepCopy(const lldb::OptionValueSP &new_parent) const
OptionValueArgs * GetAsArgs()
OptionValueArray * GetAsArray()
OptionValueFileSpec * GetAsFileSpec()
Definition: OptionValue.cpp:69
static bool IsSettingExperimental(llvm::StringRef setting)
static llvm::StringRef GetExperimentalSettingsName()
virtual lldb::OptionValuePropertiesSP GetValueProperties() const
const lldb::OptionValueSP & GetValue() const
Definition: Property.h:45
bool IsValid() const
Definition: Property.h:51
An error handling class.
Definition: Status.h:44
bool Success() const
Test for success condition.
Definition: Status.cpp:278
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
size_t PutChar(char ch)
Definition: Stream.cpp:131
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:155
A class that represents a running process on the host machine.
llvm::ArrayRef< PropertyDefinition > PropertyDefinitions
Definition: Property.h:33
VarSetOperationType
Settable state variable types.
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::OptionValueProperties > OptionValuePropertiesSP
Definition: lldb-forward.h:385
std::shared_ptr< lldb_private::OptionValue > OptionValueSP
Definition: lldb-forward.h:382