Add the new Args / entry-access API.

The long-term goal here is to get rid of the functions
GetArgumentAtIndex() and GetQuoteCharAtIndex(), instead
replacing them with operator based access and range-based for
enumeration.  There are a lot of callsites, though, so the
changes will be done incrementally, starting with this one.

Differential Revision: https://reviews.llvm.org/D26883

llvm-svn: 287597
This commit is contained in:
Zachary Turner 2016-11-21 23:18:07 +00:00
parent c2cd4e004c
commit 1c55c9b5bf
8 changed files with 93 additions and 97 deletions

View File

@ -150,9 +150,14 @@ public:
const char *GetArgumentAtIndex(size_t idx) const;
llvm::ArrayRef<ArgEntry> entries() const { return m_entries; }
char GetArgumentQuoteCharAtIndex(size_t idx) const;
auto begin() const { return m_entries.begin(); }
auto end() const { return m_entries.end(); }
size_t size() const { return GetArgumentCount(); }
const ArgEntry &operator[](size_t n) const { return m_entries[n]; }
//------------------------------------------------------------------
/// Gets the argument vector.
///

View File

@ -122,13 +122,12 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
llvm::StringRef range_from;
llvm::StringRef range_to;
llvm::StringRef current_arg;
const size_t num_old_args = old_args.GetArgumentCount();
std::set<std::string> names_found;
for (size_t i = 0; i < num_old_args; ++i) {
for (size_t i = 0; i < old_args.size(); ++i) {
bool is_range = false;
current_arg = old_args.GetArgumentAtIndex(i);
current_arg = old_args[i].ref;
if (!allow_locations && current_arg.contains('.')) {
result.AppendErrorWithFormat(
"Breakpoint locations not allowed, saw location: %s.",
@ -152,19 +151,17 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
return;
} else
names_found.insert(current_arg);
} else if ((i + 2 < num_old_args) &&
BreakpointID::IsRangeIdentifier(
old_args.GetArgumentAtIndex(i + 1)) &&
} else if ((i + 2 < old_args.size()) &&
BreakpointID::IsRangeIdentifier(old_args[i + 1].ref) &&
BreakpointID::IsValidIDExpression(current_arg) &&
BreakpointID::IsValidIDExpression(
old_args.GetArgumentAtIndex(i + 2))) {
BreakpointID::IsValidIDExpression(old_args[i + 2].ref)) {
range_from = current_arg;
range_to = old_args.GetArgumentAtIndex(i + 2);
range_to = old_args[i + 2].ref;
is_range = true;
i = i + 2;
} else {
// See if user has specified id.*
llvm::StringRef tmp_str = old_args.GetArgumentAtIndex(i);
llvm::StringRef tmp_str = old_args[i].ref;
size_t pos = tmp_str.find('.');
if (pos != llvm::StringRef::npos) {
llvm::StringRef bp_id_str = tmp_str.substr(0, pos);

View File

@ -1476,12 +1476,12 @@ public:
int match_start_point, int max_return_elements,
bool &word_complete,
StringList &matches) override {
std::string completion_str(input.GetArgumentAtIndex(cursor_index));
completion_str.erase(cursor_char_position);
llvm::StringRef completion_str = input[cursor_index].ref;
completion_str = completion_str.take_front(cursor_char_position);
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
completion_str.c_str(), match_start_point, max_return_elements, nullptr,
completion_str, match_start_point, max_return_elements, nullptr,
word_complete, matches);
return matches.GetSize();
}

View File

@ -473,12 +473,12 @@ public:
bool &word_complete,
StringList &matches) override {
// Arguments are the standard source file completer.
std::string completion_str(input.GetArgumentAtIndex(cursor_index));
completion_str.erase(cursor_char_position);
auto completion_str = input[cursor_index].ref;
completion_str = completion_str.take_front(cursor_char_position);
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
completion_str.c_str(), match_start_point, max_return_elements, nullptr,
completion_str, match_start_point, max_return_elements, nullptr,
word_complete, matches);
return matches.GetSize();
}

View File

@ -1558,9 +1558,8 @@ protected:
int num_signals_set = 0;
if (num_args > 0) {
for (size_t i = 0; i < num_args; ++i) {
int32_t signo = signals_sp->GetSignalNumberFromName(
signal_args.GetArgumentAtIndex(i));
for (const auto &arg : signal_args) {
int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
// Casting the actions as bools here should be okay, because
// VerifyCommandOptionValue guarantees
@ -1576,7 +1575,7 @@ protected:
++num_signals_set;
} else {
result.AppendErrorWithFormat("Invalid signal name '%s'\n",
signal_args.GetArgumentAtIndex(i));
arg.c_str());
}
}
} else {

View File

@ -293,15 +293,10 @@ protected:
bool DoExecute(Args &args, CommandReturnObject &result) override {
result.SetStatus(eReturnStatusSuccessFinishResult);
const size_t argc = args.GetArgumentCount();
if (!args.empty()) {
// TODO: Convert this to StringRef based enumeration. Requires converting
// DumpPropertyValue first.
for (size_t i = 0; i < argc; ++i) {
const char *property_path = args.GetArgumentAtIndex(i);
for (const auto &arg : args) {
Error error(m_interpreter.GetDebugger().DumpPropertyValue(
&m_exe_ctx, result.GetOutputStream(), property_path,
&m_exe_ctx, result.GetOutputStream(), arg.ref,
OptionValue::eDumpGroupValue));
if (error.Success()) {
result.GetOutputStream().EOL();

View File

@ -1859,9 +1859,8 @@ int CommandInterpreter::HandleCompletion(
// put an empty string in element 0.
std::string command_partial_str;
if (cursor_index >= 0)
command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
parsed_line.GetArgumentAtIndex(cursor_index) +
cursor_char_position);
command_partial_str =
parsed_line[cursor_index].ref.take_front(cursor_char_position);
std::string common_prefix;
matches.LongestCommonPrefix(common_prefix);
@ -1872,7 +1871,7 @@ int CommandInterpreter::HandleCompletion(
// Only do this if the completer told us this was a complete word,
// however...
if (num_command_matches == 1 && word_complete) {
char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
char quote_char = parsed_line[cursor_index].quote;
common_prefix =
Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
if (quote_char != '\0')

View File

@ -101,73 +101,74 @@ Error OptionValueDictionary::SetArgs(const Args &args, VarSetOperationType op) {
case eVarSetOperationAppend:
case eVarSetOperationReplace:
case eVarSetOperationAssign:
if (argc > 0) {
for (size_t i = 0; i < argc; ++i) {
llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
if (!key_and_value.empty()) {
if (key_and_value.find('=') == llvm::StringRef::npos) {
error.SetErrorString(
"assign operation takes one or more key=value arguments");
return error;
}
std::pair<llvm::StringRef, llvm::StringRef> kvp(
key_and_value.split('='));
llvm::StringRef key = kvp.first;
bool key_valid = false;
if (!key.empty()) {
if (key.front() == '[') {
// Key name starts with '[', so the key value must be in single or
// double quotes like:
// ['<key>']
// ["<key>"]
if ((key.size() > 2) && (key.back() == ']')) {
// Strip leading '[' and trailing ']'
key = key.substr(1, key.size() - 2);
const char quote_char = key.front();
if ((quote_char == '\'') || (quote_char == '"')) {
if ((key.size() > 2) && (key.back() == quote_char)) {
// Strip the quotes
key = key.substr(1, key.size() - 2);
key_valid = true;
}
} else {
// square brackets, no quotes
key_valid = true;
}
}
} else {
// No square brackets or quotes
key_valid = true;
}
}
if (!key_valid) {
error.SetErrorStringWithFormat(
"invalid key \"%s\", the key must be a bare string or "
"surrounded by brackets with optional quotes: [<key>] or "
"['<key>'] or [\"<key>\"]",
kvp.first.str().c_str());
return error;
}
lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
kvp.second.data(), m_type_mask, error));
if (value_sp) {
if (error.Fail())
return error;
m_value_was_set = true;
SetValueForKey(ConstString(key), value_sp, true);
} else {
error.SetErrorString("dictionaries that can contain multiple types "
"must subclass OptionValueArray");
}
} else {
error.SetErrorString("empty argument");
}
}
} else {
if (argc == 0) {
error.SetErrorString(
"assign operation takes one or more key=value arguments");
return error;
}
for (const auto &entry : args) {
if (entry.ref.empty()) {
error.SetErrorString("empty argument");
return error;
}
if (!entry.ref.contains('=')) {
error.SetErrorString(
"assign operation takes one or more key=value arguments");
return error;
}
llvm::StringRef key, value;
std::tie(key, value) = entry.ref.split('=');
bool key_valid = false;
if (key.empty()) {
error.SetErrorString("empty dictionary key");
return error;
}
if (key.front() == '[') {
// Key name starts with '[', so the key value must be in single or
// double quotes like:
// ['<key>']
// ["<key>"]
if ((key.size() > 2) && (key.back() == ']')) {
// Strip leading '[' and trailing ']'
key = key.substr(1, key.size() - 2);
const char quote_char = key.front();
if ((quote_char == '\'') || (quote_char == '"')) {
if ((key.size() > 2) && (key.back() == quote_char)) {
// Strip the quotes
key = key.substr(1, key.size() - 2);
key_valid = true;
}
} else {
// square brackets, no quotes
key_valid = true;
}
}
} else {
// No square brackets or quotes
key_valid = true;
}
if (!key_valid) {
error.SetErrorStringWithFormat(
"invalid key \"%s\", the key must be a bare string or "
"surrounded by brackets with optional quotes: [<key>] or "
"['<key>'] or [\"<key>\"]",
key.str().c_str());
return error;
}
lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
value.str().c_str(), m_type_mask, error));
if (value_sp) {
if (error.Fail())
return error;
m_value_was_set = true;
SetValueForKey(ConstString(key), value_sp, true);
} else {
error.SetErrorString("dictionaries that can contain multiple types "
"must subclass OptionValueArray");
}
}
break;