llvm-project

Форк
0
/
OptionValueArray.cpp 
320 строк · 10.1 Кб
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

9
#include "lldb/Interpreter/OptionValueArray.h"
10

11
#include "lldb/Utility/Args.h"
12
#include "lldb/Utility/Stream.h"
13

14
using namespace lldb;
15
using namespace lldb_private;
16

17
void OptionValueArray::DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
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,
87
                                            VarSetOperationType op) {
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, Status &error) const {
98
  if (name.empty() || name.front() != '[') {
99
    error.SetErrorStringWithFormat(
100
      "invalid value path '%s', %s values only support '[<index>]' subvalues "
101
      "where <index> is a positive or negative array index",
102
      name.str().c_str(), GetTypeAsCString());
103
    return nullptr;
104
  }
105

106
  name = name.drop_front();
107
  llvm::StringRef index, sub_value;
108
  std::tie(index, sub_value) = name.split(']');
109
  if (index.size() == name.size()) {
110
    // Couldn't find a closing bracket
111
    return nullptr;
112
  }
113

114
  const size_t array_count = m_values.size();
115
  int32_t idx = 0;
116
  if (index.getAsInteger(0, idx))
117
    return nullptr;
118

119
  uint32_t new_idx = UINT32_MAX;
120
  if (idx < 0) {
121
    // Access from the end of the array if the index is negative
122
    new_idx = array_count - idx;
123
  } else {
124
    // Just a standard index
125
    new_idx = idx;
126
  }
127

128
  if (new_idx < array_count) {
129
    if (m_values[new_idx]) {
130
      if (!sub_value.empty())
131
        return m_values[new_idx]->GetSubValue(exe_ctx, sub_value, error);
132
      else
133
        return m_values[new_idx];
134
    }
135
  } else {
136
    if (array_count == 0)
137
      error.SetErrorStringWithFormat(
138
          "index %i is not valid for an empty array", idx);
139
    else if (idx > 0)
140
      error.SetErrorStringWithFormat(
141
          "index %i out of range, valid values are 0 through %" PRIu64,
142
          idx, (uint64_t)(array_count - 1));
143
    else
144
      error.SetErrorStringWithFormat("negative index %i out of range, "
145
                                      "valid values are -1 through "
146
                                      "-%" PRIu64,
147
                                      idx, (uint64_t)array_count);
148
  }
149
  return OptionValueSP();
150
}
151

152
size_t OptionValueArray::GetArgs(Args &args) const {
153
  args.Clear();
154
  const uint32_t size = m_values.size();
155
  for (uint32_t i = 0; i < size; ++i) {
156
    auto string_value = m_values[i]->GetValueAs<llvm::StringRef>();
157
    if (string_value)
158
      args.AppendArgument(*string_value);
159
  }
160

161
  return args.GetArgumentCount();
162
}
163

164
Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) {
165
  Status error;
166
  const size_t argc = args.GetArgumentCount();
167
  switch (op) {
168
  case eVarSetOperationInvalid:
169
    error.SetErrorString("unsupported operation");
170
    break;
171

172
  case eVarSetOperationInsertBefore:
173
  case eVarSetOperationInsertAfter:
174
    if (argc > 1) {
175
      uint32_t idx;
176
      const uint32_t count = GetSize();
177
      if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
178
        error.SetErrorStringWithFormat(
179
            "invalid insert array index %s, index must be 0 through %u",
180
            args.GetArgumentAtIndex(0), count);
181
      } else {
182
        if (op == eVarSetOperationInsertAfter)
183
          ++idx;
184
        for (size_t i = 1; i < argc; ++i, ++idx) {
185
          lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
186
              args.GetArgumentAtIndex(i), m_type_mask, error));
187
          if (value_sp) {
188
            if (error.Fail())
189
              return error;
190
            if (idx >= m_values.size())
191
              m_values.push_back(value_sp);
192
            else
193
              m_values.insert(m_values.begin() + idx, value_sp);
194
          } else {
195
            error.SetErrorString(
196
                "array of complex types must subclass OptionValueArray");
197
            return error;
198
          }
199
        }
200
      }
201
    } else {
202
      error.SetErrorString("insert operation takes an array index followed by "
203
                           "one or more values");
204
    }
205
    break;
206

207
  case eVarSetOperationRemove:
208
    if (argc > 0) {
209
      const uint32_t size = m_values.size();
210
      std::vector<int> remove_indexes;
211
      bool all_indexes_valid = true;
212
      size_t i;
213
      for (i = 0; i < argc; ++i) {
214
        size_t idx;
215
        if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx) || idx >= size) {
216
          all_indexes_valid = false;
217
          break;
218
        } else
219
          remove_indexes.push_back(idx);
220
      }
221

222
      if (all_indexes_valid) {
223
        size_t num_remove_indexes = remove_indexes.size();
224
        if (num_remove_indexes) {
225
          // Sort and then erase in reverse so indexes are always valid
226
          if (num_remove_indexes > 1) {
227
            llvm::sort(remove_indexes);
228
            for (std::vector<int>::const_reverse_iterator
229
                     pos = remove_indexes.rbegin(),
230
                     end = remove_indexes.rend();
231
                 pos != end; ++pos) {
232
              m_values.erase(m_values.begin() + *pos);
233
            }
234
          } else {
235
            // Only one index
236
            m_values.erase(m_values.begin() + remove_indexes.front());
237
          }
238
        }
239
      } else {
240
        error.SetErrorStringWithFormat(
241
            "invalid array index '%s', aborting remove operation",
242
            args.GetArgumentAtIndex(i));
243
      }
244
    } else {
245
      error.SetErrorString("remove operation takes one or more array indices");
246
    }
247
    break;
248

249
  case eVarSetOperationClear:
250
    Clear();
251
    break;
252

253
  case eVarSetOperationReplace:
254
    if (argc > 1) {
255
      uint32_t idx;
256
      const uint32_t count = GetSize();
257
      if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
258
        error.SetErrorStringWithFormat(
259
            "invalid replace array index %s, index must be 0 through %u",
260
            args.GetArgumentAtIndex(0), count);
261
      } else {
262
        for (size_t i = 1; i < argc; ++i, ++idx) {
263
          lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
264
              args.GetArgumentAtIndex(i), m_type_mask, error));
265
          if (value_sp) {
266
            if (error.Fail())
267
              return error;
268
            if (idx < count)
269
              m_values[idx] = value_sp;
270
            else
271
              m_values.push_back(value_sp);
272
          } else {
273
            error.SetErrorString(
274
                "array of complex types must subclass OptionValueArray");
275
            return error;
276
          }
277
        }
278
      }
279
    } else {
280
      error.SetErrorString("replace operation takes an array index followed by "
281
                           "one or more values");
282
    }
283
    break;
284

285
  case eVarSetOperationAssign:
286
    m_values.clear();
287
    // Fall through to append case
288
    [[fallthrough]];
289
  case eVarSetOperationAppend:
290
    for (size_t i = 0; i < argc; ++i) {
291
      lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
292
          args.GetArgumentAtIndex(i), m_type_mask, error));
293
      if (value_sp) {
294
        if (error.Fail())
295
          return error;
296
        m_value_was_set = true;
297
        AppendValue(value_sp);
298
      } else {
299
        error.SetErrorString(
300
            "array of complex types must subclass OptionValueArray");
301
      }
302
    }
303
    break;
304
  }
305
  return error;
306
}
307

308
OptionValueSP
309
OptionValueArray::DeepCopy(const OptionValueSP &new_parent) const {
310
  auto copy_sp = OptionValue::DeepCopy(new_parent);
311
  // copy_sp->GetAsArray cannot be used here as it doesn't work for derived
312
  // types that override GetType returning a different value.
313
  auto *array_value_ptr = static_cast<OptionValueArray *>(copy_sp.get());
314
  lldbassert(array_value_ptr);
315

316
  for (auto &value : array_value_ptr->m_values)
317
    value = value->DeepCopy(copy_sp);
318

319
  return copy_sp;
320
}
321

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.