| 1 | //===-- OptionValueEnumeration.cpp ----------------------------------------===// |
| 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 | #include "lldb/Interpreter/OptionValueEnumeration.h" |
| 10 | |
| 11 | #include "lldb/Utility/StringList.h" |
| 12 | |
| 13 | using namespace lldb; |
| 14 | using namespace lldb_private; |
| 15 | |
| 16 | OptionValueEnumeration::OptionValueEnumeration( |
| 17 | const OptionEnumValues &enumerators, enum_type value) |
| 18 | : m_current_value(value), m_default_value(value) { |
| 19 | SetEnumerations(enumerators); |
| 20 | } |
| 21 | |
| 22 | void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx, |
| 23 | Stream &strm, uint32_t dump_mask) { |
| 24 | if (dump_mask & eDumpOptionType) |
| 25 | strm.Printf(format: "(%s)" , GetTypeAsCString()); |
| 26 | if (dump_mask & eDumpOptionValue) { |
| 27 | if (dump_mask & eDumpOptionType) |
| 28 | strm.PutCString(cstr: " = " ); |
| 29 | const size_t count = m_enumerations.GetSize(); |
| 30 | for (size_t i = 0; i < count; ++i) { |
| 31 | if (m_enumerations.GetValueAtIndexUnchecked(idx: i).value == m_current_value) { |
| 32 | strm.PutCString(cstr: m_enumerations.GetCStringAtIndex(idx: i).GetStringRef()); |
| 33 | return; |
| 34 | } |
| 35 | } |
| 36 | strm.Printf(format: "%" PRIu64, (uint64_t)m_current_value); |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | llvm::json::Value |
| 41 | OptionValueEnumeration::ToJSON(const ExecutionContext *exe_ctx) const { |
| 42 | for (const auto &enums : m_enumerations) { |
| 43 | if (enums.value.value == m_current_value) |
| 44 | return enums.cstring.GetStringRef(); |
| 45 | } |
| 46 | |
| 47 | return std::to_string(val: static_cast<uint64_t>(m_current_value)); |
| 48 | } |
| 49 | |
| 50 | Status OptionValueEnumeration::SetValueFromString(llvm::StringRef value, |
| 51 | VarSetOperationType op) { |
| 52 | Status error; |
| 53 | switch (op) { |
| 54 | case eVarSetOperationClear: |
| 55 | Clear(); |
| 56 | NotifyValueChanged(); |
| 57 | break; |
| 58 | |
| 59 | case eVarSetOperationReplace: |
| 60 | case eVarSetOperationAssign: { |
| 61 | ConstString const_enumerator_name(value.trim()); |
| 62 | const EnumerationMapEntry *enumerator_entry = |
| 63 | m_enumerations.FindFirstValueForName(unique_cstr: const_enumerator_name); |
| 64 | if (enumerator_entry) { |
| 65 | m_current_value = enumerator_entry->value.value; |
| 66 | NotifyValueChanged(); |
| 67 | } else { |
| 68 | StreamString error_strm; |
| 69 | error_strm.Printf(format: "invalid enumeration value '%s'" , value.str().c_str()); |
| 70 | const size_t count = m_enumerations.GetSize(); |
| 71 | if (count) { |
| 72 | error_strm.Printf(format: ", valid values are: %s" , |
| 73 | m_enumerations.GetCStringAtIndex(idx: 0).GetCString()); |
| 74 | for (size_t i = 1; i < count; ++i) { |
| 75 | error_strm.Printf(format: ", %s" , |
| 76 | m_enumerations.GetCStringAtIndex(idx: i).GetCString()); |
| 77 | } |
| 78 | } |
| 79 | error = Status(error_strm.GetString().str()); |
| 80 | } |
| 81 | break; |
| 82 | } |
| 83 | |
| 84 | case eVarSetOperationInsertBefore: |
| 85 | case eVarSetOperationInsertAfter: |
| 86 | case eVarSetOperationRemove: |
| 87 | case eVarSetOperationAppend: |
| 88 | case eVarSetOperationInvalid: |
| 89 | error = OptionValue::SetValueFromString(value, op); |
| 90 | break; |
| 91 | } |
| 92 | return error; |
| 93 | } |
| 94 | |
| 95 | void OptionValueEnumeration::SetEnumerations( |
| 96 | const OptionEnumValues &enumerators) { |
| 97 | m_enumerations.Clear(); |
| 98 | |
| 99 | for (const auto &enumerator : enumerators) { |
| 100 | ConstString const_enumerator_name(enumerator.string_value); |
| 101 | EnumeratorInfo enumerator_info = {.value: enumerator.value, .description: enumerator.usage}; |
| 102 | m_enumerations.Append(unique_cstr: const_enumerator_name, value: enumerator_info); |
| 103 | } |
| 104 | |
| 105 | m_enumerations.Sort(); |
| 106 | } |
| 107 | |
| 108 | void OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter, |
| 109 | CompletionRequest &request) { |
| 110 | const uint32_t num_enumerators = m_enumerations.GetSize(); |
| 111 | if (!request.GetCursorArgumentPrefix().empty()) { |
| 112 | for (size_t i = 0; i < num_enumerators; ++i) { |
| 113 | llvm::StringRef name = m_enumerations.GetCStringAtIndex(idx: i).GetStringRef(); |
| 114 | request.TryCompleteCurrentArg(completion: name); |
| 115 | } |
| 116 | return; |
| 117 | } |
| 118 | for (size_t i = 0; i < num_enumerators; ++i) |
| 119 | request.AddCompletion(completion: m_enumerations.GetCStringAtIndex(idx: i).GetStringRef()); |
| 120 | } |
| 121 | |