1 //===-- OptionValuePathMappings.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/OptionValuePathMappings.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Stream.h"
17 #include "lldb/Host/StringConvert.h"
18 #include "lldb/Interpreter/Args.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
22
23 void
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)24 OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
25 {
26 if (dump_mask & eDumpOptionType)
27 strm.Printf ("(%s)", GetTypeAsCString ());
28 if (dump_mask & eDumpOptionValue)
29 {
30 if (dump_mask & eDumpOptionType)
31 strm.Printf (" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
32 m_path_mappings.Dump(&strm);
33 }
34 }
35
36 Error
SetValueFromString(llvm::StringRef value,VarSetOperationType op)37 OptionValuePathMappings::SetValueFromString (llvm::StringRef value, VarSetOperationType op)
38 {
39 Error error;
40 Args args(value.str().c_str());
41 const size_t argc = args.GetArgumentCount();
42
43 switch (op)
44 {
45 case eVarSetOperationClear:
46 Clear ();
47 NotifyValueChanged();
48 break;
49
50 case eVarSetOperationReplace:
51 // Must be at least one index + 1 pair of paths, and the pair count must be even
52 if (argc >= 3 && (((argc - 1) & 1) == 0))
53 {
54 uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
55 const uint32_t count = m_path_mappings.GetSize();
56 if (idx > count)
57 {
58 error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
59 }
60 else
61 {
62 for (size_t i=1; i<argc; i += 2, ++idx)
63 {
64 ConstString a(args.GetArgumentAtIndex(i));
65 ConstString b(args.GetArgumentAtIndex(i+1));
66 if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
67 m_path_mappings.Append(a, b, m_notify_changes);
68 }
69 NotifyValueChanged();
70 }
71 }
72 else
73 {
74 error.SetErrorString("replace operation takes an array index followed by one or more path pairs");
75 }
76 break;
77
78
79
80 case eVarSetOperationAssign:
81 if (argc < 2 || (argc & 1))
82 {
83 error.SetErrorString("assign operation takes one or more path pairs");
84 break;
85 }
86 m_path_mappings.Clear(m_notify_changes);
87 // Fall through to append case
88 case eVarSetOperationAppend:
89 if (argc < 2 || (argc & 1))
90 {
91 error.SetErrorString("append operation takes one or more path pairs");
92 break;
93 }
94 else
95 {
96 for (size_t i=0; i<argc; i += 2)
97 {
98 ConstString a(args.GetArgumentAtIndex(i));
99 ConstString b(args.GetArgumentAtIndex(i+1));
100 m_path_mappings.Append(a, b, m_notify_changes);
101 m_value_was_set = true;
102 }
103 NotifyValueChanged();
104 }
105 break;
106
107 case eVarSetOperationInsertBefore:
108 case eVarSetOperationInsertAfter:
109 // Must be at least one index + 1 pair of paths, and the pair count must be even
110 if (argc >= 3 && (((argc - 1) & 1) == 0))
111 {
112 uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
113 const uint32_t count = m_path_mappings.GetSize();
114 if (idx > count)
115 {
116 error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
117 }
118 else
119 {
120 if (op == eVarSetOperationInsertAfter)
121 ++idx;
122 for (size_t i=1; i<argc; i += 2, ++idx)
123 {
124 ConstString a(args.GetArgumentAtIndex(i));
125 ConstString b(args.GetArgumentAtIndex(i+1));
126 m_path_mappings.Insert (a, b, idx, m_notify_changes);
127 }
128 NotifyValueChanged();
129 }
130 }
131 else
132 {
133 error.SetErrorString("insert operation takes an array index followed by one or more path pairs");
134 }
135 break;
136
137 case eVarSetOperationRemove:
138 if (argc > 0)
139 {
140 std::vector<int> remove_indexes;
141 bool all_indexes_valid = true;
142 size_t i;
143 for (i=0; all_indexes_valid && i<argc; ++i)
144 {
145 const int idx = StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
146 if (idx == INT32_MAX)
147 all_indexes_valid = false;
148 else
149 remove_indexes.push_back(idx);
150 }
151
152 if (all_indexes_valid)
153 {
154 size_t num_remove_indexes = remove_indexes.size();
155 if (num_remove_indexes)
156 {
157 // Sort and then erase in reverse so indexes are always valid
158 std::sort(remove_indexes.begin(), remove_indexes.end());
159 for (size_t j=num_remove_indexes-1; j<num_remove_indexes; ++j)
160 {
161 m_path_mappings.Remove (j, m_notify_changes);
162 }
163 }
164 NotifyValueChanged();
165 }
166 else
167 {
168 error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
169 }
170 }
171 else
172 {
173 error.SetErrorString("remove operation takes one or more array index");
174 }
175 break;
176
177 case eVarSetOperationInvalid:
178 error = OptionValue::SetValueFromString (value, op);
179 break;
180 }
181 return error;
182 }
183
184 lldb::OptionValueSP
DeepCopy() const185 OptionValuePathMappings::DeepCopy () const
186 {
187 return OptionValueSP(new OptionValuePathMappings(*this));
188 }
189