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 | |