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