1 //===-- OptionValue.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_OPTIONVALUE_H
10 #define LLDB_INTERPRETER_OPTIONVALUE_H
11 
12 #include "lldb/Core/FormatEntity.h"
13 #include "lldb/Utility/ArchSpec.h"
14 #include "lldb/Utility/Cloneable.h"
15 #include "lldb/Utility/CompletionRequest.h"
16 #include "lldb/Utility/ConstString.h"
17 #include "lldb/Utility/FileSpec.h"
18 #include "lldb/Utility/FileSpecList.h"
19 #include "lldb/Utility/Status.h"
20 #include "lldb/Utility/StringList.h"
21 #include "lldb/Utility/UUID.h"
22 #include "lldb/lldb-defines.h"
23 #include "lldb/lldb-private-enumerations.h"
24 #include "lldb/lldb-private-interfaces.h"
25 #include "llvm/Support/JSON.h"
26 
27 namespace lldb_private {
28 
29 // OptionValue
30 class OptionValue {
31 public:
32   enum Type {
33     eTypeInvalid = 0,
34     eTypeArch,
35     eTypeArgs,
36     eTypeArray,
37     eTypeBoolean,
38     eTypeChar,
39     eTypeDictionary,
40     eTypeEnum,
41     eTypeFileLineColumn,
42     eTypeFileSpec,
43     eTypeFileSpecList,
44     eTypeFormat,
45     eTypeLanguage,
46     eTypePathMap,
47     eTypeProperties,
48     eTypeRegex,
49     eTypeSInt64,
50     eTypeString,
51     eTypeUInt64,
52     eTypeUUID,
53     eTypeFormatEntity
54   };
55 
56   enum {
57     eDumpOptionName = (1u << 0),
58     eDumpOptionType = (1u << 1),
59     eDumpOptionValue = (1u << 2),
60     eDumpOptionDescription = (1u << 3),
61     eDumpOptionRaw = (1u << 4),
62     eDumpOptionCommand = (1u << 5),
63     eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue),
64     eDumpGroupHelp =
65         (eDumpOptionName | eDumpOptionType | eDumpOptionDescription),
66     eDumpGroupExport = (eDumpOptionCommand | eDumpOptionName | eDumpOptionValue)
67   };
68 
69   OptionValue() = default;
70 
71   virtual ~OptionValue() = default;
72 
73   // Subclasses should override these functions
74   virtual Type GetType() const = 0;
75 
76   // If this value is always hidden, the avoid showing any info on this value,
77   // just show the info for the child values.
78   virtual bool ValueIsTransparent() const {
79     return GetType() == eTypeProperties;
80   }
81 
82   virtual const char *GetTypeAsCString() const {
83     return GetBuiltinTypeAsCString(GetType());
84   }
85 
86   static const char *GetBuiltinTypeAsCString(Type t);
87 
88   virtual void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
89                          uint32_t dump_mask) = 0;
90 
91   // TODO: make this function pure virtual after implementing it in all
92   // child classes.
93   virtual llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) {
94     // Return nullptr which will create a llvm::json::Value() that is a NULL
95     // value. No setting should ever really have a NULL value in JSON. This
96     // indicates an error occurred and if/when we add a FromJSON() it will know
97     // to fail if someone tries to set it with a NULL JSON value.
98     return nullptr;
99   }
100 
101   virtual Status
102   SetValueFromString(llvm::StringRef value,
103                      VarSetOperationType op = eVarSetOperationAssign);
104 
105   virtual void Clear() = 0;
106 
107   virtual lldb::OptionValueSP
108   DeepCopy(const lldb::OptionValueSP &new_parent) const;
109 
110   virtual void AutoComplete(CommandInterpreter &interpreter,
111                             CompletionRequest &request);
112 
113   // Subclasses can override these functions
114   virtual lldb::OptionValueSP GetSubValue(const ExecutionContext *exe_ctx,
115                                           llvm::StringRef name,
116                                           Status &error) const {
117     error.SetErrorStringWithFormatv("'{0}' is not a valid subvalue", name);
118     return lldb::OptionValueSP();
119   }
120 
121   virtual Status SetSubValue(const ExecutionContext *exe_ctx,
122                              VarSetOperationType op, llvm::StringRef name,
123                              llvm::StringRef value);
124 
125   virtual bool IsAggregateValue() const { return false; }
126 
127   virtual llvm::StringRef GetName() const { return llvm::StringRef(); }
128 
129   virtual bool DumpQualifiedName(Stream &strm) const;
130 
131   // Subclasses should NOT override these functions as they use the above
132   // functions to implement functionality
133   uint32_t GetTypeAsMask() { return 1u << GetType(); }
134 
135   static uint32_t ConvertTypeToMask(OptionValue::Type type) {
136     return 1u << type;
137   }
138 
139   static OptionValue::Type ConvertTypeMaskToType(uint32_t type_mask) {
140     // If only one bit is set, then return an appropriate enumeration
141     switch (type_mask) {
142     case 1u << eTypeArch:
143       return eTypeArch;
144     case 1u << eTypeArgs:
145       return eTypeArgs;
146     case 1u << eTypeArray:
147       return eTypeArray;
148     case 1u << eTypeBoolean:
149       return eTypeBoolean;
150     case 1u << eTypeChar:
151       return eTypeChar;
152     case 1u << eTypeDictionary:
153       return eTypeDictionary;
154     case 1u << eTypeEnum:
155       return eTypeEnum;
156     case 1u << eTypeFileLineColumn:
157       return eTypeFileLineColumn;
158     case 1u << eTypeFileSpec:
159       return eTypeFileSpec;
160     case 1u << eTypeFileSpecList:
161       return eTypeFileSpecList;
162     case 1u << eTypeFormat:
163       return eTypeFormat;
164     case 1u << eTypeLanguage:
165       return eTypeLanguage;
166     case 1u << eTypePathMap:
167       return eTypePathMap;
168     case 1u << eTypeProperties:
169       return eTypeProperties;
170     case 1u << eTypeRegex:
171       return eTypeRegex;
172     case 1u << eTypeSInt64:
173       return eTypeSInt64;
174     case 1u << eTypeString:
175       return eTypeString;
176     case 1u << eTypeUInt64:
177       return eTypeUInt64;
178     case 1u << eTypeUUID:
179       return eTypeUUID;
180     }
181     // Else return invalid
182     return eTypeInvalid;
183   }
184 
185   static lldb::OptionValueSP
186   CreateValueFromCStringForTypeMask(const char *value_cstr, uint32_t type_mask,
187                                     Status &error);
188 
189   OptionValueArch *GetAsArch();
190   const OptionValueArch *GetAsArch() const;
191 
192   OptionValueArray *GetAsArray();
193   const OptionValueArray *GetAsArray() const;
194 
195   OptionValueArgs *GetAsArgs();
196   const OptionValueArgs *GetAsArgs() const;
197 
198   OptionValueBoolean *GetAsBoolean();
199   const OptionValueBoolean *GetAsBoolean() const;
200 
201   OptionValueChar *GetAsChar();
202   const OptionValueChar *GetAsChar() const;
203 
204   OptionValueDictionary *GetAsDictionary();
205   const OptionValueDictionary *GetAsDictionary() const;
206 
207   OptionValueEnumeration *GetAsEnumeration();
208   const OptionValueEnumeration *GetAsEnumeration() const;
209 
210   OptionValueFileSpec *GetAsFileSpec();
211   const OptionValueFileSpec *GetAsFileSpec() const;
212 
213   OptionValueFileSpecList *GetAsFileSpecList();
214   const OptionValueFileSpecList *GetAsFileSpecList() const;
215 
216   OptionValueFormat *GetAsFormat();
217   const OptionValueFormat *GetAsFormat() const;
218 
219   OptionValueLanguage *GetAsLanguage();
220   const OptionValueLanguage *GetAsLanguage() const;
221 
222   OptionValuePathMappings *GetAsPathMappings();
223   const OptionValuePathMappings *GetAsPathMappings() const;
224 
225   OptionValueProperties *GetAsProperties();
226   const OptionValueProperties *GetAsProperties() const;
227 
228   OptionValueRegex *GetAsRegex();
229   const OptionValueRegex *GetAsRegex() const;
230 
231   OptionValueSInt64 *GetAsSInt64();
232   const OptionValueSInt64 *GetAsSInt64() const;
233 
234   OptionValueString *GetAsString();
235   const OptionValueString *GetAsString() const;
236 
237   OptionValueUInt64 *GetAsUInt64();
238   const OptionValueUInt64 *GetAsUInt64() const;
239 
240   OptionValueUUID *GetAsUUID();
241   const OptionValueUUID *GetAsUUID() const;
242 
243   OptionValueFormatEntity *GetAsFormatEntity();
244   const OptionValueFormatEntity *GetAsFormatEntity() const;
245 
246   bool AppendFileSpecValue(FileSpec file_spec);
247 
248   bool OptionWasSet() const { return m_value_was_set; }
249 
250   void SetOptionWasSet() { m_value_was_set = true; }
251 
252   void SetParent(const lldb::OptionValueSP &parent_sp) {
253     m_parent_wp = parent_sp;
254   }
255 
256   lldb::OptionValueSP GetParent() const { return m_parent_wp.lock(); }
257 
258   void SetValueChangedCallback(std::function<void()> callback) {
259     m_callback = std::move(callback);
260   }
261 
262   void NotifyValueChanged() {
263     if (m_callback)
264       m_callback();
265   }
266 
267   template <typename T, std::enable_if_t<!std::is_pointer_v<T>, bool> = true>
268   std::optional<T> GetValueAs() const {
269     if constexpr (std::is_same_v<T, uint64_t>)
270       return GetUInt64Value();
271     if constexpr (std::is_same_v<T, int64_t>)
272       return GetSInt64Value();
273     if constexpr (std::is_same_v<T, bool>)
274       return GetBooleanValue();
275     if constexpr (std::is_same_v<T, char>)
276       return GetCharValue();
277     if constexpr (std::is_same_v<T, lldb::Format>)
278       return GetFormatValue();
279     if constexpr (std::is_same_v<T, FileSpec>)
280       return GetFileSpecValue();
281     if constexpr (std::is_same_v<T, FileSpecList>)
282       return GetFileSpecListValue();
283     if constexpr (std::is_same_v<T, lldb::LanguageType>)
284       return GetLanguageValue();
285     if constexpr (std::is_same_v<T, llvm::StringRef>)
286       return GetStringValue();
287     if constexpr (std::is_same_v<T, ArchSpec>)
288       return GetArchSpecValue();
289     if constexpr (std::is_enum_v<T>)
290       if (std::optional<int64_t> value = GetEnumerationValue())
291         return static_cast<T>(*value);
292     return {};
293   }
294 
295   template <typename T,
296             typename U = typename std::remove_const<
297                 typename std::remove_pointer<T>::type>::type,
298             std::enable_if_t<std::is_pointer_v<T>, bool> = true>
299   T GetValueAs() const {
300     if constexpr (std::is_same_v<U, FormatEntity::Entry>)
301       return GetFormatEntity();
302     if constexpr (std::is_same_v<U, RegularExpression>)
303       return GetRegexValue();
304     return {};
305   }
306 
307   bool SetValueAs(bool v) { return SetBooleanValue(v); }
308 
309   bool SetValueAs(char v) { return SetCharValue(v); }
310 
311   bool SetValueAs(uint64_t v) { return SetUInt64Value(v); }
312 
313   bool SetValueAs(int64_t v) { return SetSInt64Value(v); }
314 
315   bool SetValueAs(UUID v) { return SetUUIDValue(v); }
316 
317   bool SetValueAs(llvm::StringRef v) { return SetStringValue(v); }
318 
319   bool SetValueAs(lldb::LanguageType v) { return SetLanguageValue(v); }
320 
321   bool SetValueAs(lldb::Format v) { return SetFormatValue(v); }
322 
323   bool SetValueAs(FileSpec v) { return SetFileSpecValue(v); }
324 
325   bool SetValueAs(ArchSpec v) { return SetArchSpecValue(v); }
326 
327   template <typename T, std::enable_if_t<std::is_enum_v<T>, bool> = true>
328   bool SetValueAs(T t) {
329     return SetEnumerationValue(t);
330   }
331 
332 protected:
333   using TopmostBase = OptionValue;
334 
335   // Must be overriden by a derived class for correct downcasting the result of
336   // DeepCopy to it. Inherit from Cloneable to avoid doing this manually.
337   virtual lldb::OptionValueSP Clone() const = 0;
338 
339   lldb::OptionValueWP m_parent_wp;
340   std::function<void()> m_callback;
341   bool m_value_was_set = false; // This can be used to see if a value has been
342                                 // set by a call to SetValueFromCString(). It is
343                                 // often handy to know if an option value was
344                                 // set from the command line or as a setting,
345                                 // versus if we just have the default value that
346                                 // was already populated in the option value.
347 private:
348   std::optional<ArchSpec> GetArchSpecValue() const;
349   bool SetArchSpecValue(ArchSpec arch_spec);
350 
351   std::optional<bool> GetBooleanValue() const;
352   bool SetBooleanValue(bool new_value);
353 
354   std::optional<char> GetCharValue() const;
355   bool SetCharValue(char new_value);
356 
357   std::optional<int64_t> GetEnumerationValue() const;
358   bool SetEnumerationValue(int64_t value);
359 
360   std::optional<FileSpec> GetFileSpecValue() const;
361   bool SetFileSpecValue(FileSpec file_spec);
362 
363   std::optional<FileSpecList> GetFileSpecListValue() const;
364 
365   std::optional<int64_t> GetSInt64Value() const;
366   bool SetSInt64Value(int64_t new_value);
367 
368   std::optional<uint64_t> GetUInt64Value() const;
369   bool SetUInt64Value(uint64_t new_value);
370 
371   std::optional<lldb::Format> GetFormatValue() const;
372   bool SetFormatValue(lldb::Format new_value);
373 
374   std::optional<lldb::LanguageType> GetLanguageValue() const;
375   bool SetLanguageValue(lldb::LanguageType new_language);
376 
377   std::optional<llvm::StringRef> GetStringValue() const;
378   bool SetStringValue(llvm::StringRef new_value);
379 
380   std::optional<UUID> GetUUIDValue() const;
381   bool SetUUIDValue(const UUID &uuid);
382 
383   const FormatEntity::Entry *GetFormatEntity() const;
384   const RegularExpression *GetRegexValue() const;
385 };
386 
387 } // namespace lldb_private
388 
389 #endif // LLDB_INTERPRETER_OPTIONVALUE_H
390