LLDB  mainline
OptionValueArray.cpp
Go to the documentation of this file.
1 //===-- OptionValueArray.cpp ------------------------------------*- C++ -*-===//
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 
10 
12 #include "lldb/Utility/Args.h"
13 #include "lldb/Utility/Stream.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
19  uint32_t dump_mask) {
20  const Type array_element_type = ConvertTypeMaskToType(m_type_mask);
21  if (dump_mask & eDumpOptionType) {
22  if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
23  strm.Printf("(%s of %ss)", GetTypeAsCString(),
24  GetBuiltinTypeAsCString(array_element_type));
25  else
26  strm.Printf("(%s)", GetTypeAsCString());
27  }
28  if (dump_mask & eDumpOptionValue) {
29  const bool one_line = dump_mask & eDumpOptionCommand;
30  const uint32_t size = m_values.size();
31  if (dump_mask & eDumpOptionType)
32  strm.Printf(" =%s", (m_values.size() > 0 && !one_line) ? "\n" : "");
33  if (!one_line)
34  strm.IndentMore();
35  for (uint32_t i = 0; i < size; ++i) {
36  if (!one_line) {
37  strm.Indent();
38  strm.Printf("[%u]: ", i);
39  }
40  const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
41  switch (array_element_type) {
42  default:
43  case eTypeArray:
44  case eTypeDictionary:
45  case eTypeProperties:
46  case eTypeFileSpecList:
47  case eTypePathMap:
48  m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
49  break;
50 
51  case eTypeBoolean:
52  case eTypeChar:
53  case eTypeEnum:
54  case eTypeFileSpec:
55  case eTypeFormat:
56  case eTypeSInt64:
57  case eTypeString:
58  case eTypeUInt64:
59  case eTypeUUID:
60  // No need to show the type for dictionaries of simple items
61  m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) |
62  extra_dump_options);
63  break;
64  }
65 
66  if (!one_line) {
67  if (i < (size - 1))
68  strm.EOL();
69  } else {
70  strm << ' ';
71  }
72  }
73  if (!one_line)
74  strm.IndentLess();
75  }
76 }
77 
78 Status OptionValueArray::SetValueFromString(llvm::StringRef value,
80  Args args(value.str());
81  Status error = SetArgs(args, op);
82  if (error.Success())
83  NotifyValueChanged();
84  return error;
85 }
86 
87 lldb::OptionValueSP
88 OptionValueArray::GetSubValue(const ExecutionContext *exe_ctx,
89  llvm::StringRef name, bool will_modify,
90  Status &error) const {
91  if (name.empty() || name.front() != '[') {
93  "invalid value path '%s', %s values only support '[<index>]' subvalues "
94  "where <index> is a positive or negative array index",
95  name.str().c_str(), GetTypeAsCString());
96  return nullptr;
97  }
98 
99  name = name.drop_front();
100  llvm::StringRef index, sub_value;
101  std::tie(index, sub_value) = name.split(']');
102  if (index.size() == name.size()) {
103  // Couldn't find a closing bracket
104  return nullptr;
105  }
106 
107  const size_t array_count = m_values.size();
108  int32_t idx = 0;
109  if (index.getAsInteger(0, idx))
110  return nullptr;
111 
112  uint32_t new_idx = UINT32_MAX;
113  if (idx < 0) {
114  // Access from the end of the array if the index is negative
115  new_idx = array_count - idx;
116  } else {
117  // Just a standard index
118  new_idx = idx;
119  }
120 
121  if (new_idx < array_count) {
122  if (m_values[new_idx]) {
123  if (!sub_value.empty())
124  return m_values[new_idx]->GetSubValue(exe_ctx, sub_value,
125  will_modify, error);
126  else
127  return m_values[new_idx];
128  }
129  } else {
130  if (array_count == 0)
132  "index %i is not valid for an empty array", idx);
133  else if (idx > 0)
135  "index %i out of range, valid values are 0 through %" PRIu64,
136  idx, (uint64_t)(array_count - 1));
137  else
138  error.SetErrorStringWithFormat("negative index %i out of range, "
139  "valid values are -1 through "
140  "-%" PRIu64,
141  idx, (uint64_t)array_count);
142  }
143  return OptionValueSP();
144 }
145 
146 size_t OptionValueArray::GetArgs(Args &args) const {
147  args.Clear();
148  const uint32_t size = m_values.size();
149  for (uint32_t i = 0; i < size; ++i) {
150  llvm::StringRef string_value = m_values[i]->GetStringValue();
151  if (!string_value.empty())
152  args.AppendArgument(string_value);
153  }
154 
155  return args.GetArgumentCount();
156 }
157 
158 Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) {
159  Status error;
160  const size_t argc = args.GetArgumentCount();
161  switch (op) {
163  error.SetErrorString("unsupported operation");
164  break;
165 
168  if (argc > 1) {
169  uint32_t idx =
171  const uint32_t count = GetSize();
172  if (idx > count) {
174  "invalid insert array index %u, index must be 0 through %u", idx,
175  count);
176  } else {
177  if (op == eVarSetOperationInsertAfter)
178  ++idx;
179  for (size_t i = 1; i < argc; ++i, ++idx) {
180  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
181  args.GetArgumentAtIndex(i), m_type_mask, error));
182  if (value_sp) {
183  if (error.Fail())
184  return error;
185  if (idx >= m_values.size())
186  m_values.push_back(value_sp);
187  else
188  m_values.insert(m_values.begin() + idx, value_sp);
189  } else {
190  error.SetErrorString(
191  "array of complex types must subclass OptionValueArray");
192  return error;
193  }
194  }
195  }
196  } else {
197  error.SetErrorString("insert operation takes an array index followed by "
198  "one or more values");
199  }
200  break;
201 
203  if (argc > 0) {
204  const uint32_t size = m_values.size();
205  std::vector<int> remove_indexes;
206  bool all_indexes_valid = true;
207  size_t i;
208  for (i = 0; i < argc; ++i) {
209  const size_t idx =
211  if (idx >= size) {
212  all_indexes_valid = false;
213  break;
214  } else
215  remove_indexes.push_back(idx);
216  }
217 
218  if (all_indexes_valid) {
219  size_t num_remove_indexes = remove_indexes.size();
220  if (num_remove_indexes) {
221  // Sort and then erase in reverse so indexes are always valid
222  if (num_remove_indexes > 1) {
223  llvm::sort(remove_indexes.begin(), remove_indexes.end());
224  for (std::vector<int>::const_reverse_iterator
225  pos = remove_indexes.rbegin(),
226  end = remove_indexes.rend();
227  pos != end; ++pos) {
228  m_values.erase(m_values.begin() + *pos);
229  }
230  } else {
231  // Only one index
232  m_values.erase(m_values.begin() + remove_indexes.front());
233  }
234  }
235  } else {
237  "invalid array index '%s', aborting remove operation",
238  args.GetArgumentAtIndex(i));
239  }
240  } else {
241  error.SetErrorString("remove operation takes one or more array indices");
242  }
243  break;
244 
246  Clear();
247  break;
248 
250  if (argc > 1) {
251  uint32_t idx =
253  const uint32_t count = GetSize();
254  if (idx > count) {
256  "invalid replace array index %u, index must be 0 through %u", idx,
257  count);
258  } else {
259  for (size_t i = 1; i < argc; ++i, ++idx) {
260  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
261  args.GetArgumentAtIndex(i), m_type_mask, error));
262  if (value_sp) {
263  if (error.Fail())
264  return error;
265  if (idx < count)
266  m_values[idx] = value_sp;
267  else
268  m_values.push_back(value_sp);
269  } else {
270  error.SetErrorString(
271  "array of complex types must subclass OptionValueArray");
272  return error;
273  }
274  }
275  }
276  } else {
277  error.SetErrorString("replace operation takes an array index followed by "
278  "one or more values");
279  }
280  break;
281 
283  m_values.clear();
284  // Fall through to append case
285  LLVM_FALLTHROUGH;
287  for (size_t i = 0; i < argc; ++i) {
288  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
289  args.GetArgumentAtIndex(i), m_type_mask, error));
290  if (value_sp) {
291  if (error.Fail())
292  return error;
293  m_value_was_set = true;
294  AppendValue(value_sp);
295  } else {
296  error.SetErrorString(
297  "array of complex types must subclass OptionValueArray");
298  }
299  }
300  break;
301  }
302  return error;
303 }
304 
305 lldb::OptionValueSP OptionValueArray::DeepCopy() const {
306  OptionValueArray *copied_array =
307  new OptionValueArray(m_type_mask, m_raw_value_dump);
308  lldb::OptionValueSP copied_value_sp(copied_array);
309  *static_cast<OptionValue *>(copied_array) = *this;
310  copied_array->m_callback = m_callback;
311  const uint32_t size = m_values.size();
312  for (uint32_t i = 0; i < size; ++i) {
313  copied_array->AppendValue(m_values[i]->DeepCopy());
314  }
315  return copied_value_sp;
316 }
A command line argument class.
Definition: Args.h:32
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
OptionValueChangedCallback m_callback
Definition: OptionValue.h:325
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.cpp:254
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
int32_t ToSInt32(const char *s, int32_t fail_value=0, int base=0, bool *success_ptr=nullptr)
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx. ...
Definition: Args.cpp:256
#define UINT32_MAX
Definition: lldb-defines.h:31
VarSetOperationType
Settable state variable types.
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:127
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
void IndentLess(int amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:221
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
Definition: SBAddress.h:15
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition: Args.cpp:321
size_t Indent(const char *s=nullptr)
Indent the current line in the stream.
Definition: Stream.cpp:131
uint32_t ToUInt32(const char *s, uint32_t fail_value=0, int base=0, bool *success_ptr=nullptr)
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
void IndentMore(int amount=2)
Increment the current indentation level.
Definition: Stream.cpp:218
#define INT32_MAX
Definition: lldb-defines.h:27
static bool DumpValue(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const FormatEntity::Entry &entry, ValueObject *valobj)
An error handling class.
Definition: Status.h:44
bool AppendValue(const lldb::OptionValueSP &value_sp)