LLDB  mainline
OptionValueArray.cpp
Go to the documentation of this file.
1 //===-- OptionValueArray.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 
10 
11 #include "lldb/Utility/Args.h"
12 #include "lldb/Utility/Stream.h"
13 
14 using namespace lldb;
15 using namespace lldb_private;
16 
18  uint32_t dump_mask) {
19  const Type array_element_type = ConvertTypeMaskToType(m_type_mask);
20  if (dump_mask & eDumpOptionType) {
21  if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
22  strm.Printf("(%s of %ss)", GetTypeAsCString(),
23  GetBuiltinTypeAsCString(array_element_type));
24  else
25  strm.Printf("(%s)", GetTypeAsCString());
26  }
27  if (dump_mask & eDumpOptionValue) {
28  const bool one_line = dump_mask & eDumpOptionCommand;
29  const uint32_t size = m_values.size();
30  if (dump_mask & eDumpOptionType)
31  strm.Printf(" =%s", (m_values.size() > 0 && !one_line) ? "\n" : "");
32  if (!one_line)
33  strm.IndentMore();
34  for (uint32_t i = 0; i < size; ++i) {
35  if (!one_line) {
36  strm.Indent();
37  strm.Printf("[%u]: ", i);
38  }
39  const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
40  switch (array_element_type) {
41  default:
42  case eTypeArray:
43  case eTypeDictionary:
44  case eTypeProperties:
45  case eTypeFileSpecList:
46  case eTypePathMap:
47  m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
48  break;
49 
50  case eTypeBoolean:
51  case eTypeChar:
52  case eTypeEnum:
53  case eTypeFileSpec:
54  case eTypeFileLineColumn:
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() != '[') {
92  error.SetErrorStringWithFormat(
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)
131  error.SetErrorStringWithFormat(
132  "index %i is not valid for an empty array", idx);
133  else if (idx > 0)
134  error.SetErrorStringWithFormat(
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;
170  const uint32_t count = GetSize();
171  if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
172  error.SetErrorStringWithFormat(
173  "invalid insert array index %s, index must be 0 through %u",
174  args.GetArgumentAtIndex(0), count);
175  } else {
176  if (op == eVarSetOperationInsertAfter)
177  ++idx;
178  for (size_t i = 1; i < argc; ++i, ++idx) {
179  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
180  args.GetArgumentAtIndex(i), m_type_mask, error));
181  if (value_sp) {
182  if (error.Fail())
183  return error;
184  if (idx >= m_values.size())
185  m_values.push_back(value_sp);
186  else
187  m_values.insert(m_values.begin() + idx, value_sp);
188  } else {
189  error.SetErrorString(
190  "array of complex types must subclass OptionValueArray");
191  return error;
192  }
193  }
194  }
195  } else {
196  error.SetErrorString("insert operation takes an array index followed by "
197  "one or more values");
198  }
199  break;
200 
202  if (argc > 0) {
203  const uint32_t size = m_values.size();
204  std::vector<int> remove_indexes;
205  bool all_indexes_valid = true;
206  size_t i;
207  for (i = 0; i < argc; ++i) {
208  size_t idx;
209  if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx) || idx >= size) {
210  all_indexes_valid = false;
211  break;
212  } else
213  remove_indexes.push_back(idx);
214  }
215 
216  if (all_indexes_valid) {
217  size_t num_remove_indexes = remove_indexes.size();
218  if (num_remove_indexes) {
219  // Sort and then erase in reverse so indexes are always valid
220  if (num_remove_indexes > 1) {
221  llvm::sort(remove_indexes.begin(), remove_indexes.end());
222  for (std::vector<int>::const_reverse_iterator
223  pos = remove_indexes.rbegin(),
224  end = remove_indexes.rend();
225  pos != end; ++pos) {
226  m_values.erase(m_values.begin() + *pos);
227  }
228  } else {
229  // Only one index
230  m_values.erase(m_values.begin() + remove_indexes.front());
231  }
232  }
233  } else {
234  error.SetErrorStringWithFormat(
235  "invalid array index '%s', aborting remove operation",
236  args.GetArgumentAtIndex(i));
237  }
238  } else {
239  error.SetErrorString("remove operation takes one or more array indices");
240  }
241  break;
242 
244  Clear();
245  break;
246 
248  if (argc > 1) {
249  uint32_t idx;
250  const uint32_t count = GetSize();
251  if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
252  error.SetErrorStringWithFormat(
253  "invalid replace array index %s, index must be 0 through %u",
254  args.GetArgumentAtIndex(0), count);
255  } else {
256  for (size_t i = 1; i < argc; ++i, ++idx) {
257  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
258  args.GetArgumentAtIndex(i), m_type_mask, error));
259  if (value_sp) {
260  if (error.Fail())
261  return error;
262  if (idx < count)
263  m_values[idx] = value_sp;
264  else
265  m_values.push_back(value_sp);
266  } else {
267  error.SetErrorString(
268  "array of complex types must subclass OptionValueArray");
269  return error;
270  }
271  }
272  }
273  } else {
274  error.SetErrorString("replace operation takes an array index followed by "
275  "one or more values");
276  }
277  break;
278 
280  m_values.clear();
281  // Fall through to append case
282  LLVM_FALLTHROUGH;
284  for (size_t i = 0; i < argc; ++i) {
285  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
286  args.GetArgumentAtIndex(i), m_type_mask, error));
287  if (value_sp) {
288  if (error.Fail())
289  return error;
290  m_value_was_set = true;
291  AppendValue(value_sp);
292  } else {
293  error.SetErrorString(
294  "array of complex types must subclass OptionValueArray");
295  }
296  }
297  break;
298  }
299  return error;
300 }
301 
302 OptionValueSP
303 OptionValueArray::DeepCopy(const OptionValueSP &new_parent) const {
304  auto copy_sp = OptionValue::DeepCopy(new_parent);
305  // copy_sp->GetAsArray cannot be used here as it doesn't work for derived
306  // types that override GetType returning a different value.
307  auto *array_value_ptr = static_cast<OptionValueArray *>(copy_sp.get());
308  lldbassert(array_value_ptr);
309 
310  for (auto &value : array_value_ptr->m_values)
311  value = value->DeepCopy(copy_sp);
312 
313  return copy_sp;
314 }
lldb_private::eVarSetOperationInsertBefore
@ eVarSetOperationInsertBefore
Definition: lldb-private-enumerations.h:85
lldb_private::Stream::IndentLess
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:171
lldb_private::eVarSetOperationReplace
@ eVarSetOperationReplace
Definition: lldb-private-enumerations.h:84
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::Args::AppendArgument
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:318
lldb_private::Args::Clear
void Clear()
Clear the arguments.
Definition: Args.cpp:374
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Args
Definition: Args.h:33
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::VarSetOperationType
VarSetOperationType
Settable state variable types.
Definition: lldb-private-enumerations.h:83
lldb_private::Stream::Indent
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition: Stream.cpp:130
Args.h
lldb_private::eVarSetOperationAppend
@ eVarSetOperationAppend
Definition: lldb-private-enumerations.h:88
OptionValueArray.h
lldbassert
#define lldbassert(x)
Definition: LLDBAssert.h:15
lldb_private::Status
Definition: Status.h:44
lldb_private::OptionValue::Type
Type
Definition: OptionValue.h:26
lldb_private::Args::GetArgumentAtIndex
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:259
uint32_t
lldb_private::Stream::IndentMore
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition: Stream.cpp:168
lldb_private::Stream::EOL
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:128
UINT32_MAX
#define UINT32_MAX
Definition: lldb-defines.h:31
lldb_private::eVarSetOperationRemove
@ eVarSetOperationRemove
Definition: lldb-private-enumerations.h:87
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::eVarSetOperationInvalid
@ eVarSetOperationInvalid
Definition: lldb-private-enumerations.h:91
Stream.h
lldb_private::Args::GetArgumentCount
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:118
lldb
Definition: SBAddress.h:15
lldb_private::eVarSetOperationClear
@ eVarSetOperationClear
Definition: lldb-private-enumerations.h:89
DumpValue
static bool DumpValue(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const FormatEntity::Entry &entry, ValueObject *valobj)
Definition: FormatEntity.cpp:673
lldb_private::eVarSetOperationInsertAfter
@ eVarSetOperationInsertAfter
Definition: lldb-private-enumerations.h:86
lldb_private::eVarSetOperationAssign
@ eVarSetOperationAssign
Definition: lldb-private-enumerations.h:90
lldb_private::OptionValueArray
Definition: OptionValueArray.h:18