1//===-- OptionValueProperties.h ---------------------------------*- C++ -*-===//
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#ifndef LLDB_INTERPRETER_OPTIONVALUEPROPERTIES_H
10#define LLDB_INTERPRETER_OPTIONVALUEPROPERTIES_H
11
12#include <vector>
13
14#include "lldb/Core/FormatEntity.h"
15#include "lldb/Core/UniqueCStringMap.h"
16#include "lldb/Interpreter/OptionValue.h"
17#include "lldb/Interpreter/Property.h"
18
19namespace lldb_private {
20class Properties;
21
22class OptionValueProperties
23    : public Cloneable<OptionValueProperties, OptionValue>,
24      public std::enable_shared_from_this<OptionValueProperties> {
25public:
26  OptionValueProperties() = default;
27
28  OptionValueProperties(llvm::StringRef name);
29
30  ~OptionValueProperties() override = default;
31
32  Type GetType() const override { return eTypeProperties; }
33
34  void Clear() override;
35
36  static lldb::OptionValuePropertiesSP
37  CreateLocalCopy(const Properties &global_properties);
38
39  lldb::OptionValueSP
40  DeepCopy(const lldb::OptionValueSP &new_parent) const override;
41
42  Status
43  SetValueFromString(llvm::StringRef value,
44                     VarSetOperationType op = eVarSetOperationAssign) override;
45
46  void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
47                 uint32_t dump_mask) override;
48
49  llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
50
51  llvm::StringRef GetName() const override { return m_name; }
52
53  virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx,
54                                   Stream &strm, llvm::StringRef property_path,
55                                   uint32_t dump_mask, bool is_json = false);
56
57  virtual void DumpAllDescriptions(CommandInterpreter &interpreter,
58                                   Stream &strm) const;
59
60  void Apropos(llvm::StringRef keyword,
61               std::vector<const Property *> &matching_properties) const;
62
63  void Initialize(const PropertyDefinitions &setting_definitions);
64
65  // Subclass specific functions
66
67  // Get the index of a property given its exact name in this property
68  // collection, "name" can't be a path to a property path that refers to a
69  // property within a property
70  virtual size_t GetPropertyIndex(llvm::StringRef name) const;
71
72  // Get a property by exact name exists in this property collection, name can
73  // not be a path to a property path that refers to a property within a
74  // property
75  virtual const Property *
76  GetProperty(llvm::StringRef name,
77              const ExecutionContext *exe_ctx = nullptr) const;
78
79  virtual const Property *
80  GetPropertyAtIndex(size_t idx,
81                     const ExecutionContext *exe_ctx = nullptr) const {
82    return ProtectedGetPropertyAtIndex(idx);
83  }
84
85  // Property can be a property path like
86  // "target.process.extra-startup-command"
87  virtual const Property *
88  GetPropertyAtPath(const ExecutionContext *exe_ctx,
89                    llvm::StringRef property_path) const;
90
91  virtual lldb::OptionValueSP
92  GetPropertyValueAtIndex(size_t idx, const ExecutionContext *exe_ctx) const;
93
94  virtual lldb::OptionValueSP GetValueForKey(const ExecutionContext *exe_ctx,
95                                             llvm::StringRef key) const;
96
97  lldb::OptionValueSP GetSubValue(const ExecutionContext *exe_ctx,
98                                  llvm::StringRef name,
99                                  Status &error) const override;
100
101  Status SetSubValue(const ExecutionContext *exe_ctx, VarSetOperationType op,
102                     llvm::StringRef path, llvm::StringRef value) override;
103
104  bool
105  GetPropertyAtIndexAsArgs(size_t idx, Args &args,
106                           const ExecutionContext *exe_ctx = nullptr) const;
107
108  bool SetPropertyAtIndexFromArgs(size_t idx, const Args &args,
109                                  const ExecutionContext *exe_ctx = nullptr);
110
111  OptionValueDictionary *GetPropertyAtIndexAsOptionValueDictionary(
112      size_t idx, const ExecutionContext *exe_ctx = nullptr) const;
113
114  OptionValueSInt64 *GetPropertyAtIndexAsOptionValueSInt64(
115      size_t idx, const ExecutionContext *exe_ctx = nullptr) const;
116
117  OptionValueUInt64 *GetPropertyAtIndexAsOptionValueUInt64(
118      size_t idx, const ExecutionContext *exe_ctx = nullptr) const;
119
120  OptionValueString *GetPropertyAtIndexAsOptionValueString(
121      size_t idx, const ExecutionContext *exe_ctx = nullptr) const;
122
123  OptionValueFileSpec *GetPropertyAtIndexAsOptionValueFileSpec(
124      size_t idx, const ExecutionContext *exe_ctx = nullptr) const;
125
126  OptionValuePathMappings *GetPropertyAtIndexAsOptionValuePathMappings(
127      size_t idx, const ExecutionContext *exe_ctx = nullptr) const;
128
129  OptionValueFileSpecList *GetPropertyAtIndexAsOptionValueFileSpecList(
130      size_t idx, const ExecutionContext *exe_ctx = nullptr) const;
131
132  void AppendProperty(llvm::StringRef name, llvm::StringRef desc,
133                      bool is_global, const lldb::OptionValueSP &value_sp);
134
135  lldb::OptionValuePropertiesSP GetSubProperty(const ExecutionContext *exe_ctx,
136                                               llvm::StringRef name);
137
138  void SetValueChangedCallback(size_t property_idx,
139                               std::function<void()> callback);
140
141  template <typename T>
142  auto GetPropertyAtIndexAs(size_t idx,
143                            const ExecutionContext *exe_ctx = nullptr) const {
144    if (const Property *property = GetPropertyAtIndex(idx, exe_ctx)) {
145      if (OptionValue *value = property->GetValue().get())
146        return value->GetValueAs<T>();
147    }
148    if constexpr (std::is_pointer_v<T>)
149      return T{nullptr};
150    else
151      return std::optional<T>{std::nullopt};
152  }
153
154  template <typename T>
155  bool SetPropertyAtIndex(size_t idx, T t,
156                          const ExecutionContext *exe_ctx = nullptr) const {
157    if (const Property *property = GetPropertyAtIndex(idx, exe_ctx)) {
158      if (OptionValue *value = property->GetValue().get()) {
159        value->SetValueAs(t);
160        return true;
161      }
162    }
163    return false;
164  }
165
166protected:
167  Property *ProtectedGetPropertyAtIndex(size_t idx) {
168    assert(idx < m_properties.size() && "invalid property index");
169    return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr);
170  }
171
172  const Property *ProtectedGetPropertyAtIndex(size_t idx) const {
173    assert(idx < m_properties.size() && "invalid property index");
174    return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr);
175  }
176
177  std::string m_name;
178  std::vector<Property> m_properties;
179  llvm::StringMap<size_t> m_name_to_index;
180};
181
182} // namespace lldb_private
183
184#endif // LLDB_INTERPRETER_OPTIONVALUEPROPERTIES_H
185