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