//===-- OptionValue.h -------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLDB_INTERPRETER_OPTIONVALUE_H #define LLDB_INTERPRETER_OPTIONVALUE_H #include "lldb/Core/FormatEntity.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Cloneable.h" #include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/FileSpecList.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StringList.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" #include "llvm/Support/JSON.h" #include namespace lldb_private { // OptionValue class OptionValue { public: enum Type { eTypeInvalid = 0, eTypeArch, eTypeArgs, eTypeArray, eTypeBoolean, eTypeChar, eTypeDictionary, eTypeEnum, eTypeFileLineColumn, eTypeFileSpec, eTypeFileSpecList, eTypeFormat, eTypeLanguage, eTypePathMap, eTypeProperties, eTypeRegex, eTypeSInt64, eTypeString, eTypeUInt64, eTypeUUID, eTypeFormatEntity }; enum { eDumpOptionName = (1u << 0), eDumpOptionType = (1u << 1), eDumpOptionValue = (1u << 2), eDumpOptionDescription = (1u << 3), eDumpOptionRaw = (1u << 4), eDumpOptionCommand = (1u << 5), eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue), eDumpGroupHelp = (eDumpOptionName | eDumpOptionType | eDumpOptionDescription), eDumpGroupExport = (eDumpOptionCommand | eDumpOptionName | eDumpOptionValue) }; OptionValue() = default; virtual ~OptionValue() = default; OptionValue(const OptionValue &other); OptionValue& operator=(const OptionValue &other); // Subclasses should override these functions virtual Type GetType() const = 0; // If this value is always hidden, the avoid showing any info on this value, // just show the info for the child values. virtual bool ValueIsTransparent() const { return GetType() == eTypeProperties; } virtual const char *GetTypeAsCString() const { return GetBuiltinTypeAsCString(GetType()); } static const char *GetBuiltinTypeAsCString(Type t); virtual void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) = 0; // TODO: make this function pure virtual after implementing it in all // child classes. virtual llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) { // Return nullptr which will create a llvm::json::Value() that is a NULL // value. No setting should ever really have a NULL value in JSON. This // indicates an error occurred and if/when we add a FromJSON() it will know // to fail if someone tries to set it with a NULL JSON value. return nullptr; } virtual Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual void Clear() = 0; virtual lldb::OptionValueSP DeepCopy(const lldb::OptionValueSP &new_parent) const; virtual void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request); // Subclasses can override these functions virtual lldb::OptionValueSP GetSubValue(const ExecutionContext *exe_ctx, llvm::StringRef name, Status &error) const { error.SetErrorStringWithFormatv("'{0}' is not a valid subvalue", name); return lldb::OptionValueSP(); } virtual Status SetSubValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef name, llvm::StringRef value); virtual bool IsAggregateValue() const { return false; } virtual llvm::StringRef GetName() const { return llvm::StringRef(); } virtual bool DumpQualifiedName(Stream &strm) const; // Subclasses should NOT override these functions as they use the above // functions to implement functionality uint32_t GetTypeAsMask() { return 1u << GetType(); } static uint32_t ConvertTypeToMask(OptionValue::Type type) { return 1u << type; } static OptionValue::Type ConvertTypeMaskToType(uint32_t type_mask) { // If only one bit is set, then return an appropriate enumeration switch (type_mask) { case 1u << eTypeArch: return eTypeArch; case 1u << eTypeArgs: return eTypeArgs; case 1u << eTypeArray: return eTypeArray; case 1u << eTypeBoolean: return eTypeBoolean; case 1u << eTypeChar: return eTypeChar; case 1u << eTypeDictionary: return eTypeDictionary; case 1u << eTypeEnum: return eTypeEnum; case 1u << eTypeFileLineColumn: return eTypeFileLineColumn; case 1u << eTypeFileSpec: return eTypeFileSpec; case 1u << eTypeFileSpecList: return eTypeFileSpecList; case 1u << eTypeFormat: return eTypeFormat; case 1u << eTypeLanguage: return eTypeLanguage; case 1u << eTypePathMap: return eTypePathMap; case 1u << eTypeProperties: return eTypeProperties; case 1u << eTypeRegex: return eTypeRegex; case 1u << eTypeSInt64: return eTypeSInt64; case 1u << eTypeString: return eTypeString; case 1u << eTypeUInt64: return eTypeUInt64; case 1u << eTypeUUID: return eTypeUUID; } // Else return invalid return eTypeInvalid; } static lldb::OptionValueSP CreateValueFromCStringForTypeMask(const char *value_cstr, uint32_t type_mask, Status &error); OptionValueArch *GetAsArch(); const OptionValueArch *GetAsArch() const; OptionValueArray *GetAsArray(); const OptionValueArray *GetAsArray() const; OptionValueArgs *GetAsArgs(); const OptionValueArgs *GetAsArgs() const; OptionValueBoolean *GetAsBoolean(); const OptionValueBoolean *GetAsBoolean() const; OptionValueChar *GetAsChar(); const OptionValueChar *GetAsChar() const; OptionValueDictionary *GetAsDictionary(); const OptionValueDictionary *GetAsDictionary() const; OptionValueEnumeration *GetAsEnumeration(); const OptionValueEnumeration *GetAsEnumeration() const; OptionValueFileSpec *GetAsFileSpec(); const OptionValueFileSpec *GetAsFileSpec() const; OptionValueFileSpecList *GetAsFileSpecList(); const OptionValueFileSpecList *GetAsFileSpecList() const; OptionValueFormat *GetAsFormat(); const OptionValueFormat *GetAsFormat() const; OptionValueLanguage *GetAsLanguage(); const OptionValueLanguage *GetAsLanguage() const; OptionValuePathMappings *GetAsPathMappings(); const OptionValuePathMappings *GetAsPathMappings() const; OptionValueProperties *GetAsProperties(); const OptionValueProperties *GetAsProperties() const; OptionValueRegex *GetAsRegex(); const OptionValueRegex *GetAsRegex() const; OptionValueSInt64 *GetAsSInt64(); const OptionValueSInt64 *GetAsSInt64() const; OptionValueString *GetAsString(); const OptionValueString *GetAsString() const; OptionValueUInt64 *GetAsUInt64(); const OptionValueUInt64 *GetAsUInt64() const; OptionValueUUID *GetAsUUID(); const OptionValueUUID *GetAsUUID() const; OptionValueFormatEntity *GetAsFormatEntity(); const OptionValueFormatEntity *GetAsFormatEntity() const; bool AppendFileSpecValue(FileSpec file_spec); bool OptionWasSet() const { return m_value_was_set; } void SetOptionWasSet() { m_value_was_set = true; } void SetParent(const lldb::OptionValueSP &parent_sp) { m_parent_wp = parent_sp; } lldb::OptionValueSP GetParent() const { return m_parent_wp.lock(); } void SetValueChangedCallback(std::function callback) { m_callback = std::move(callback); } void NotifyValueChanged() { if (m_callback) m_callback(); } template , bool> = true> std::optional GetValueAs() const { if constexpr (std::is_same_v) return GetUInt64Value(); if constexpr (std::is_same_v) return GetSInt64Value(); if constexpr (std::is_same_v) return GetBooleanValue(); if constexpr (std::is_same_v) return GetCharValue(); if constexpr (std::is_same_v) return GetFormatValue(); if constexpr (std::is_same_v) return GetFileSpecValue(); if constexpr (std::is_same_v) return GetFileSpecListValue(); if constexpr (std::is_same_v) return GetLanguageValue(); if constexpr (std::is_same_v) return GetStringValue(); if constexpr (std::is_same_v) return GetArchSpecValue(); if constexpr (std::is_enum_v) if (std::optional value = GetEnumerationValue()) return static_cast(*value); return {}; } template ::type>::type, std::enable_if_t, bool> = true> T GetValueAs() const { if constexpr (std::is_same_v) return GetFormatEntity(); if constexpr (std::is_same_v) return GetRegexValue(); return {}; } bool SetValueAs(bool v) { return SetBooleanValue(v); } bool SetValueAs(char v) { return SetCharValue(v); } bool SetValueAs(uint64_t v) { return SetUInt64Value(v); } bool SetValueAs(int64_t v) { return SetSInt64Value(v); } bool SetValueAs(UUID v) { return SetUUIDValue(v); } bool SetValueAs(llvm::StringRef v) { return SetStringValue(v); } bool SetValueAs(lldb::LanguageType v) { return SetLanguageValue(v); } bool SetValueAs(lldb::Format v) { return SetFormatValue(v); } bool SetValueAs(FileSpec v) { return SetFileSpecValue(v); } bool SetValueAs(ArchSpec v) { return SetArchSpecValue(v); } template , bool> = true> bool SetValueAs(T t) { return SetEnumerationValue(t); } protected: using TopmostBase = OptionValue; // Must be overriden by a derived class for correct downcasting the result of // DeepCopy to it. Inherit from Cloneable to avoid doing this manually. virtual lldb::OptionValueSP Clone() const = 0; lldb::OptionValueWP m_parent_wp; std::function m_callback; bool m_value_was_set = false; // This can be used to see if a value has been // set by a call to SetValueFromCString(). It is // often handy to know if an option value was // set from the command line or as a setting, // versus if we just have the default value that // was already populated in the option value. private: std::optional GetArchSpecValue() const; bool SetArchSpecValue(ArchSpec arch_spec); std::optional GetBooleanValue() const; bool SetBooleanValue(bool new_value); std::optional GetCharValue() const; bool SetCharValue(char new_value); std::optional GetEnumerationValue() const; bool SetEnumerationValue(int64_t value); std::optional GetFileSpecValue() const; bool SetFileSpecValue(FileSpec file_spec); std::optional GetFileSpecListValue() const; std::optional GetSInt64Value() const; bool SetSInt64Value(int64_t new_value); std::optional GetUInt64Value() const; bool SetUInt64Value(uint64_t new_value); std::optional GetFormatValue() const; bool SetFormatValue(lldb::Format new_value); std::optional GetLanguageValue() const; bool SetLanguageValue(lldb::LanguageType new_language); std::optional GetStringValue() const; bool SetStringValue(llvm::StringRef new_value); std::optional GetUUIDValue() const; bool SetUUIDValue(const UUID &uuid); const FormatEntity::Entry *GetFormatEntity() const; const RegularExpression *GetRegexValue() const; mutable std::mutex m_mutex; }; } // namespace lldb_private #endif // LLDB_INTERPRETER_OPTIONVALUE_H