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