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 llvm::json::Value OptionValueArray::ToJSON(const ExecutionContext *exe_ctx) {
79  llvm::json::Array json_array;
80  const uint32_t size = m_values.size();
81  for (uint32_t i = 0; i < size; ++i)
82  json_array.emplace_back(m_values[i]->ToJSON(exe_ctx));
83  return json_array;
84 }
85 
86 Status OptionValueArray::SetValueFromString(llvm::StringRef value,
88  Args args(value.str());
89  Status error = SetArgs(args, op);
90  if (error.Success())
91  NotifyValueChanged();
92  return error;
93 }
94 
95 lldb::OptionValueSP
96 OptionValueArray::GetSubValue(const ExecutionContext *exe_ctx,
97  llvm::StringRef name, bool will_modify,
98  Status &error) const {
99  if (name.empty() || name.front() != '[') {
100  error.SetErrorStringWithFormat(
101  "invalid value path '%s', %s values only support '[<index>]' subvalues "
102  "where <index> is a positive or negative array index",
103  name.str().c_str(), GetTypeAsCString());
104  return nullptr;
105  }
106 
107  name = name.drop_front();
108  llvm::StringRef index, sub_value;
109  std::tie(index, sub_value) = name.split(']');
110  if (index.size() == name.size()) {
111  // Couldn't find a closing bracket
112  return nullptr;
113  }
114 
115  const size_t array_count = m_values.size();
116  int32_t idx = 0;
117  if (index.getAsInteger(0, idx))
118  return nullptr;
119 
120  uint32_t new_idx = UINT32_MAX;
121  if (idx < 0) {
122  // Access from the end of the array if the index is negative
123  new_idx = array_count - idx;
124  } else {
125  // Just a standard index
126  new_idx = idx;
127  }
128 
129  if (new_idx < array_count) {
130  if (m_values[new_idx]) {
131  if (!sub_value.empty())
132  return m_values[new_idx]->GetSubValue(exe_ctx, sub_value,
133  will_modify, error);
134  else
135  return m_values[new_idx];
136  }
137  } else {
138  if (array_count == 0)
139  error.SetErrorStringWithFormat(
140  "index %i is not valid for an empty array", idx);
141  else if (idx > 0)
142  error.SetErrorStringWithFormat(
143  "index %i out of range, valid values are 0 through %" PRIu64,
144  idx, (uint64_t)(array_count - 1));
145  else
146  error.SetErrorStringWithFormat("negative index %i out of range, "
147  "valid values are -1 through "
148  "-%" PRIu64,
149  idx, (uint64_t)array_count);
150  }
151  return OptionValueSP();
152 }
153 
154 size_t OptionValueArray::GetArgs(Args &args) const {
155  args.Clear();
156  const uint32_t size = m_values.size();
157  for (uint32_t i = 0; i < size; ++i) {
158  llvm::StringRef string_value = m_values[i]->GetStringValue();
159  if (!string_value.empty())
160  args.AppendArgument(string_value);
161  }
162 
163  return args.GetArgumentCount();
164 }
165 
166 Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) {
167  Status error;
168  const size_t argc = args.GetArgumentCount();
169  switch (op) {
171  error.SetErrorString("unsupported operation");
172  break;
173 
176  if (argc > 1) {
177  uint32_t idx;
178  const uint32_t count = GetSize();
179  if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
180  error.SetErrorStringWithFormat(
181  "invalid insert array index %s, index must be 0 through %u",
182  args.GetArgumentAtIndex(0), count);
183  } else {
184  if (op == eVarSetOperationInsertAfter)
185  ++idx;
186  for (size_t i = 1; i < argc; ++i, ++idx) {
187  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
188  args.GetArgumentAtIndex(i), m_type_mask, error));
189  if (value_sp) {
190  if (error.Fail())
191  return error;
192  if (idx >= m_values.size())
193  m_values.push_back(value_sp);
194  else
195  m_values.insert(m_values.begin() + idx, value_sp);
196  } else {
197  error.SetErrorString(
198  "array of complex types must subclass OptionValueArray");
199  return error;
200  }
201  }
202  }
203  } else {
204  error.SetErrorString("insert operation takes an array index followed by "
205  "one or more values");
206  }
207  break;
208 
210  if (argc > 0) {
211  const uint32_t size = m_values.size();
212  std::vector<int> remove_indexes;
213  bool all_indexes_valid = true;
214  size_t i;
215  for (i = 0; i < argc; ++i) {
216  size_t idx;
217  if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx) || idx >= size) {
218  all_indexes_valid = false;
219  break;
220  } else
221  remove_indexes.push_back(idx);
222  }
223 
224  if (all_indexes_valid) {
225  size_t num_remove_indexes = remove_indexes.size();
226  if (num_remove_indexes) {
227  // Sort and then erase in reverse so indexes are always valid
228  if (num_remove_indexes > 1) {
229  llvm::sort(remove_indexes);
230  for (std::vector<int>::const_reverse_iterator
231  pos = remove_indexes.rbegin(),
232  end = remove_indexes.rend();
233  pos != end; ++pos) {
234  m_values.erase(m_values.begin() + *pos);
235  }
236  } else {
237  // Only one index
238  m_values.erase(m_values.begin() + remove_indexes.front());
239  }
240  }
241  } else {
242  error.SetErrorStringWithFormat(
243  "invalid array index '%s', aborting remove operation",
244  args.GetArgumentAtIndex(i));
245  }
246  } else {
247  error.SetErrorString("remove operation takes one or more array indices");
248  }
249  break;
250 
252  Clear();
253  break;
254 
256  if (argc > 1) {
257  uint32_t idx;
258  const uint32_t count = GetSize();
259  if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
260  error.SetErrorStringWithFormat(
261  "invalid replace array index %s, index must be 0 through %u",
262  args.GetArgumentAtIndex(0), count);
263  } else {
264  for (size_t i = 1; i < argc; ++i, ++idx) {
265  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
266  args.GetArgumentAtIndex(i), m_type_mask, error));
267  if (value_sp) {
268  if (error.Fail())
269  return error;
270  if (idx < count)
271  m_values[idx] = value_sp;
272  else
273  m_values.push_back(value_sp);
274  } else {
275  error.SetErrorString(
276  "array of complex types must subclass OptionValueArray");
277  return error;
278  }
279  }
280  }
281  } else {
282  error.SetErrorString("replace operation takes an array index followed by "
283  "one or more values");
284  }
285  break;
286 
288  m_values.clear();
289  // Fall through to append case
290  [[fallthrough]];
292  for (size_t i = 0; i < argc; ++i) {
293  lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
294  args.GetArgumentAtIndex(i), m_type_mask, error));
295  if (value_sp) {
296  if (error.Fail())
297  return error;
298  m_value_was_set = true;
299  AppendValue(value_sp);
300  } else {
301  error.SetErrorString(
302  "array of complex types must subclass OptionValueArray");
303  }
304  }
305  break;
306  }
307  return error;
308 }
309 
310 OptionValueSP
311 OptionValueArray::DeepCopy(const OptionValueSP &new_parent) const {
312  auto copy_sp = OptionValue::DeepCopy(new_parent);
313  // copy_sp->GetAsArray cannot be used here as it doesn't work for derived
314  // types that override GetType returning a different value.
315  auto *array_value_ptr = static_cast<OptionValueArray *>(copy_sp.get());
316  lldbassert(array_value_ptr);
317 
318  for (auto &value : array_value_ptr->m_values)
319  value = value->DeepCopy(copy_sp);
320 
321  return copy_sp;
322 }
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:323
lldb_private::Args::Clear
void Clear()
Clear the arguments.
Definition: Args.cpp:379
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:27
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:264
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:19
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:116
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:668
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