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