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("(%s)", GetTypeAsCString());
26   if (dump_mask & eDumpOptionValue) {
27     if (dump_mask & eDumpOptionType)
28       strm.PutCString(" = ");
29     const size_t count = m_enumerations.GetSize();
30     for (size_t i = 0; i < count; ++i) {
31       if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) {
32         strm.PutCString(m_enumerations.GetCStringAtIndex(i).GetStringRef());
33         return;
34       }
35     }
36     strm.Printf("%" PRIu64, (uint64_t)m_current_value);
37   }
38 }
39 
40 Status OptionValueEnumeration::SetValueFromString(llvm::StringRef value,
41                                                   VarSetOperationType op) {
42   Status error;
43   switch (op) {
44   case eVarSetOperationClear:
45     Clear();
46     NotifyValueChanged();
47     break;
48 
49   case eVarSetOperationReplace:
50   case eVarSetOperationAssign: {
51     ConstString const_enumerator_name(value.trim());
52     const EnumerationMapEntry *enumerator_entry =
53         m_enumerations.FindFirstValueForName(const_enumerator_name);
54     if (enumerator_entry) {
55       m_current_value = enumerator_entry->value.value;
56       NotifyValueChanged();
57     } else {
58       StreamString error_strm;
59       error_strm.Printf("invalid enumeration value '%s'", value.str().c_str());
60       const size_t count = m_enumerations.GetSize();
61       if (count) {
62         error_strm.Printf(", valid values are: %s",
63                           m_enumerations.GetCStringAtIndex(0).GetCString());
64         for (size_t i = 1; i < count; ++i) {
65           error_strm.Printf(", %s",
66                             m_enumerations.GetCStringAtIndex(i).GetCString());
67         }
68       }
69       error.SetErrorString(error_strm.GetString());
70     }
71     break;
72   }
73 
74   case eVarSetOperationInsertBefore:
75   case eVarSetOperationInsertAfter:
76   case eVarSetOperationRemove:
77   case eVarSetOperationAppend:
78   case eVarSetOperationInvalid:
79     error = OptionValue::SetValueFromString(value, op);
80     break;
81   }
82   return error;
83 }
84 
85 void OptionValueEnumeration::SetEnumerations(
86     const OptionEnumValues &enumerators) {
87   m_enumerations.Clear();
88 
89   for (const auto &enumerator : enumerators) {
90     ConstString const_enumerator_name(enumerator.string_value);
91     EnumeratorInfo enumerator_info = {enumerator.value, enumerator.usage};
92     m_enumerations.Append(const_enumerator_name, enumerator_info);
93   }
94 
95   m_enumerations.Sort();
96 }
97 
98 void OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter,
99                                           CompletionRequest &request) {
100   const uint32_t num_enumerators = m_enumerations.GetSize();
101   if (!request.GetCursorArgumentPrefix().empty()) {
102     for (size_t i = 0; i < num_enumerators; ++i) {
103       llvm::StringRef name = m_enumerations.GetCStringAtIndex(i).GetStringRef();
104       request.TryCompleteCurrentArg(name);
105     }
106     return;
107   }
108     for (size_t i = 0; i < num_enumerators; ++i)
109       request.AddCompletion(m_enumerations.GetCStringAtIndex(i).GetStringRef());
110 }
111