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 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/StringList.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 OptionValueEnumeration::OptionValueEnumeration (const OptionEnumValueElement *enumerators,
22                                                 enum_type value) :
23     OptionValue(),
24     m_current_value (value),
25     m_default_value (value),
26     m_enumerations ()
27 {
28     SetEnumerations(enumerators);
29 }
30 
31 OptionValueEnumeration::~OptionValueEnumeration()
32 {
33 }
34 
35 void
36 OptionValueEnumeration::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
37 {
38     if (dump_mask & eDumpOptionType)
39         strm.Printf ("(%s)", GetTypeAsCString ());
40     if (dump_mask & eDumpOptionValue)
41     {
42         if (dump_mask & eDumpOptionType)
43             strm.PutCString (" = ");
44         const size_t count = m_enumerations.GetSize ();
45         for (size_t i=0; i<count; ++i)
46         {
47             if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value)
48             {
49                 strm.PutCString(m_enumerations.GetCStringAtIndex(i));
50                 return;
51             }
52         }
53         strm.Printf("%" PRIu64, (uint64_t)m_current_value);
54     }
55 }
56 
57 Error
58 OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationType op)
59 {
60     Error error;
61     switch (op)
62     {
63         case eVarSetOperationClear:
64             Clear ();
65             NotifyValueChanged();
66             break;
67 
68         case eVarSetOperationReplace:
69         case eVarSetOperationAssign:
70             if (value && value[0])
71             {
72                 ConstString const_enumerator_name(llvm::StringRef(value).trim());
73                 const EnumerationMapEntry *enumerator_entry = m_enumerations.FindFirstValueForName (const_enumerator_name.GetCString());
74                 if (enumerator_entry)
75                 {
76                     m_current_value = enumerator_entry->value.value;
77                     NotifyValueChanged();
78                 }
79                 else
80                 {
81                     StreamString error_strm;
82                     error_strm.Printf("invalid enumeration value '%s'", value);
83                     const size_t count = m_enumerations.GetSize ();
84                     if (count)
85                     {
86                         error_strm.Printf(", valid values are: %s", m_enumerations.GetCStringAtIndex(0));
87                         for (size_t i=1; i<count; ++i)
88                         {
89                             error_strm.Printf (", %s", m_enumerations.GetCStringAtIndex(i));
90                         }
91                     }
92                     error.SetErrorString(error_strm.GetData());
93                 }
94             }
95             else
96             {
97                 error.SetErrorString("invalid enumeration value");
98             }
99             break;
100 
101         case eVarSetOperationInsertBefore:
102         case eVarSetOperationInsertAfter:
103         case eVarSetOperationRemove:
104         case eVarSetOperationAppend:
105         case eVarSetOperationInvalid:
106             error = OptionValue::SetValueFromCString (value, op);
107             break;
108     }
109     return error;
110 }
111 
112 void
113 OptionValueEnumeration::SetEnumerations (const OptionEnumValueElement *enumerators)
114 {
115     m_enumerations.Clear();
116     if (enumerators)
117     {
118         for (size_t i=0; enumerators[i].string_value != nullptr; ++i)
119         {
120             ConstString const_enumerator_name(enumerators[i].string_value);
121             EnumeratorInfo enumerator_info = { enumerators[i].value, enumerators[i].usage };
122             m_enumerations.Append (const_enumerator_name.GetCString(), enumerator_info);
123         }
124         m_enumerations.Sort();
125     }
126 }
127 
128 
129 lldb::OptionValueSP
130 OptionValueEnumeration::DeepCopy () const
131 {
132     return OptionValueSP(new OptionValueEnumeration(*this));
133 }
134 
135 size_t
136 OptionValueEnumeration::AutoComplete (CommandInterpreter &interpreter,
137                                       const char *s,
138                                       int match_start_point,
139                                       int max_return_elements,
140                                       bool &word_complete,
141                                       StringList &matches)
142 {
143     word_complete = false;
144     matches.Clear();
145 
146     const uint32_t num_enumerators = m_enumerations.GetSize();
147     if (s && s[0])
148     {
149         const size_t s_len = strlen(s);
150         for (size_t i=0; i<num_enumerators; ++i)
151         {
152             const char *name = m_enumerations.GetCStringAtIndex(i);
153             if (::strncmp(s, name, s_len) == 0)
154                 matches.AppendString(name);
155         }
156     }
157     else
158     {
159         // only suggest "true" or "false" by default
160         for (size_t i=0; i<num_enumerators; ++i)
161             matches.AppendString(m_enumerations.GetCStringAtIndex(i));
162     }
163     return matches.GetSize();
164 }
165 
166 
167 
168 
169