1 //===-- OptionValueEnumeration.cpp ------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Interpreter/OptionValueEnumeration.h"
11 
12 #include "lldb/Utility/StringList.h"
13 
14 using namespace lldb;
15 using namespace lldb_private;
16 
OptionValueEnumeration(const OptionEnumValues & enumerators,enum_type value)17 OptionValueEnumeration::OptionValueEnumeration(
18     const OptionEnumValues &enumerators, enum_type value)
19     : OptionValue(), m_current_value(value), m_default_value(value),
20       m_enumerations() {
21   SetEnumerations(enumerators);
22 }
23 
~OptionValueEnumeration()24 OptionValueEnumeration::~OptionValueEnumeration() {}
25 
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)26 void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx,
27                                        Stream &strm, uint32_t dump_mask) {
28   if (dump_mask & eDumpOptionType)
29     strm.Printf("(%s)", GetTypeAsCString());
30   if (dump_mask & eDumpOptionValue) {
31     if (dump_mask & eDumpOptionType)
32       strm.PutCString(" = ");
33     const size_t count = m_enumerations.GetSize();
34     for (size_t i = 0; i < count; ++i) {
35       if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) {
36         strm.PutCString(m_enumerations.GetCStringAtIndex(i).GetStringRef());
37         return;
38       }
39     }
40     strm.Printf("%" PRIu64, (uint64_t)m_current_value);
41   }
42 }
43 
SetValueFromString(llvm::StringRef value,VarSetOperationType op)44 Status OptionValueEnumeration::SetValueFromString(llvm::StringRef value,
45                                                   VarSetOperationType op) {
46   Status error;
47   switch (op) {
48   case eVarSetOperationClear:
49     Clear();
50     NotifyValueChanged();
51     break;
52 
53   case eVarSetOperationReplace:
54   case eVarSetOperationAssign: {
55     ConstString const_enumerator_name(value.trim());
56     const EnumerationMapEntry *enumerator_entry =
57         m_enumerations.FindFirstValueForName(const_enumerator_name);
58     if (enumerator_entry) {
59       m_current_value = enumerator_entry->value.value;
60       NotifyValueChanged();
61     } else {
62       StreamString error_strm;
63       error_strm.Printf("invalid enumeration value '%s'", value.str().c_str());
64       const size_t count = m_enumerations.GetSize();
65       if (count) {
66         error_strm.Printf(", valid values are: %s",
67                           m_enumerations.GetCStringAtIndex(0).GetCString());
68         for (size_t i = 1; i < count; ++i) {
69           error_strm.Printf(", %s",
70                             m_enumerations.GetCStringAtIndex(i).GetCString());
71         }
72       }
73       error.SetErrorString(error_strm.GetString());
74     }
75     break;
76   }
77 
78   case eVarSetOperationInsertBefore:
79   case eVarSetOperationInsertAfter:
80   case eVarSetOperationRemove:
81   case eVarSetOperationAppend:
82   case eVarSetOperationInvalid:
83     error = OptionValue::SetValueFromString(value, op);
84     break;
85   }
86   return error;
87 }
88 
SetEnumerations(const OptionEnumValues & enumerators)89 void OptionValueEnumeration::SetEnumerations(
90     const OptionEnumValues &enumerators) {
91   m_enumerations.Clear();
92 
93   for (const auto &enumerator : enumerators) {
94     ConstString const_enumerator_name(enumerator.string_value);
95     EnumeratorInfo enumerator_info = {enumerator.value, enumerator.usage};
96     m_enumerations.Append(const_enumerator_name, enumerator_info);
97   }
98 
99   m_enumerations.Sort();
100 }
101 
DeepCopy() const102 lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const {
103   return OptionValueSP(new OptionValueEnumeration(*this));
104 }
105 
AutoComplete(CommandInterpreter & interpreter,CompletionRequest & request)106 size_t OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter,
107                                             CompletionRequest &request) {
108   request.SetWordComplete(false);
109 
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(i).GetStringRef();
114       if (name.startswith(request.GetCursorArgumentPrefix()))
115         request.AddCompletion(name);
116     }
117   } else {
118     // only suggest "true" or "false" by default
119     for (size_t i = 0; i < num_enumerators; ++i)
120       request.AddCompletion(m_enumerations.GetCStringAtIndex(i).GetStringRef());
121   }
122   return request.GetNumberOfMatches();
123 }
124