llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp
Kate Stone b9c1b51e45 *** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style.  This kind of mass change has
*** two obvious implications:

Firstly, merging this particular commit into a downstream fork may be a huge
effort.  Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit.  The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):

    find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
    find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;

The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.

Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit.  There are alternatives available that will attempt
to look through this change and find the appropriate prior commit.  YMMV.

llvm-svn: 280751
2016-09-06 20:57:50 +00:00

393 lines
13 KiB
C++

//===-- OptionValueDictionary.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Interpreter/OptionValueDictionary.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
// Project includes
#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/OptionValueString.h"
using namespace lldb;
using namespace lldb_private;
void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx,
Stream &strm, uint32_t dump_mask) {
const Type dict_type = ConvertTypeMaskToType(m_type_mask);
if (dump_mask & eDumpOptionType) {
if (m_type_mask != eTypeInvalid)
strm.Printf("(%s of %ss)", GetTypeAsCString(),
GetBuiltinTypeAsCString(dict_type));
else
strm.Printf("(%s)", GetTypeAsCString());
}
if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
strm.PutCString(" =");
collection::iterator pos, end = m_values.end();
strm.IndentMore();
for (pos = m_values.begin(); pos != end; ++pos) {
OptionValue *option_value = pos->second.get();
strm.EOL();
strm.Indent(pos->first.GetCString());
const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
switch (dict_type) {
default:
case eTypeArray:
case eTypeDictionary:
case eTypeProperties:
case eTypeFileSpecList:
case eTypePathMap:
strm.PutChar(' ');
option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
break;
case eTypeBoolean:
case eTypeChar:
case eTypeEnum:
case eTypeFileSpec:
case eTypeFormat:
case eTypeSInt64:
case eTypeString:
case eTypeUInt64:
case eTypeUUID:
// No need to show the type for dictionaries of simple items
strm.PutCString("=");
option_value->DumpValue(exe_ctx, strm,
(dump_mask & (~eDumpOptionType)) |
extra_dump_options);
break;
}
}
strm.IndentLess();
}
}
size_t OptionValueDictionary::GetArgs(Args &args) const {
args.Clear();
collection::const_iterator pos, end = m_values.end();
for (pos = m_values.begin(); pos != end; ++pos) {
StreamString strm;
strm.Printf("%s=", pos->first.GetCString());
pos->second->DumpValue(nullptr, strm, eDumpOptionValue | eDumpOptionRaw);
args.AppendArgument(strm.GetString().c_str());
}
return args.GetArgumentCount();
}
Error OptionValueDictionary::SetArgs(const Args &args, VarSetOperationType op) {
Error error;
const size_t argc = args.GetArgumentCount();
switch (op) {
case eVarSetOperationClear:
Clear();
break;
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 {
error.SetErrorString(
"assign operation takes one or more key=value arguments");
}
break;
case eVarSetOperationRemove:
if (argc > 0) {
for (size_t i = 0; i < argc; ++i) {
ConstString key(args.GetArgumentAtIndex(i));
if (!DeleteValueForKey(key)) {
error.SetErrorStringWithFormat(
"no value found named '%s', aborting remove operation",
key.GetCString());
break;
}
}
} else {
error.SetErrorString("remove operation takes one or more key arguments");
}
break;
case eVarSetOperationInsertBefore:
case eVarSetOperationInsertAfter:
case eVarSetOperationInvalid:
error = OptionValue::SetValueFromString(llvm::StringRef(), op);
break;
}
return error;
}
Error OptionValueDictionary::SetValueFromString(llvm::StringRef value,
VarSetOperationType op) {
Args args(value.str().c_str());
Error error = SetArgs(args, op);
if (error.Success())
NotifyValueChanged();
return error;
}
lldb::OptionValueSP
OptionValueDictionary::GetSubValue(const ExecutionContext *exe_ctx,
const char *name, bool will_modify,
Error &error) const {
lldb::OptionValueSP value_sp;
if (name && name[0]) {
const char *sub_name = nullptr;
ConstString key;
const char *open_bracket = ::strchr(name, '[');
if (open_bracket) {
const char *key_start = open_bracket + 1;
const char *key_end = nullptr;
switch (open_bracket[1]) {
case '\'':
++key_start;
key_end = strchr(key_start, '\'');
if (key_end) {
if (key_end[1] == ']') {
if (key_end[2])
sub_name = key_end + 2;
} else {
error.SetErrorStringWithFormat("invalid value path '%s', single "
"quoted key names must be formatted "
"as ['<key>'] where <key> is a "
"string that doesn't contain quotes",
name);
return value_sp;
}
} else {
error.SetErrorString(
"missing '] key name terminator, key name started with ['");
return value_sp;
}
break;
case '"':
++key_start;
key_end = strchr(key_start, '"');
if (key_end) {
if (key_end[1] == ']') {
if (key_end[2])
sub_name = key_end + 2;
break;
}
error.SetErrorStringWithFormat("invalid value path '%s', double "
"quoted key names must be formatted "
"as [\"<key>\"] where <key> is a "
"string that doesn't contain quotes",
name);
return value_sp;
} else {
error.SetErrorString(
"missing \"] key name terminator, key name started with [\"");
return value_sp;
}
break;
default:
key_end = strchr(key_start, ']');
if (key_end) {
if (key_end[1])
sub_name = key_end + 1;
} else {
error.SetErrorString(
"missing ] key name terminator, key name started with [");
return value_sp;
}
break;
}
if (key_start && key_end) {
key.SetCStringWithLength(key_start, key_end - key_start);
value_sp = GetValueForKey(key);
if (value_sp) {
if (sub_name)
return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
} else {
error.SetErrorStringWithFormat(
"dictionary does not contain a value for the key name '%s'",
key.GetCString());
}
}
}
if (!value_sp && error.AsCString() == nullptr) {
error.SetErrorStringWithFormat("invalid value path '%s', %s values only "
"support '[<key>]' subvalues where <key> "
"a string value optionally delimited by "
"single or double quotes",
name, GetTypeAsCString());
}
}
return value_sp;
}
Error OptionValueDictionary::SetSubValue(const ExecutionContext *exe_ctx,
VarSetOperationType op,
const char *name, const char *value) {
Error error;
const bool will_modify = true;
lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
if (value_sp)
error = value_sp->SetValueFromString(value, op);
else {
if (error.AsCString() == nullptr)
error.SetErrorStringWithFormat("invalid value path '%s'", name);
}
return error;
}
lldb::OptionValueSP
OptionValueDictionary::GetValueForKey(const ConstString &key) const {
lldb::OptionValueSP value_sp;
collection::const_iterator pos = m_values.find(key);
if (pos != m_values.end())
value_sp = pos->second;
return value_sp;
}
const char *
OptionValueDictionary::GetStringValueForKey(const ConstString &key) {
collection::const_iterator pos = m_values.find(key);
if (pos != m_values.end()) {
OptionValueString *string_value = pos->second->GetAsString();
if (string_value)
return string_value->GetCurrentValue();
}
return nullptr;
}
bool OptionValueDictionary::SetStringValueForKey(const ConstString &key,
const char *value,
bool can_replace) {
collection::const_iterator pos = m_values.find(key);
if (pos != m_values.end()) {
if (!can_replace)
return false;
if (pos->second->GetType() == OptionValue::eTypeString) {
pos->second->SetValueFromString(value);
return true;
}
}
m_values[key] = OptionValueSP(new OptionValueString(value));
return true;
}
bool OptionValueDictionary::SetValueForKey(const ConstString &key,
const lldb::OptionValueSP &value_sp,
bool can_replace) {
// Make sure the value_sp object is allowed to contain
// values of the type passed in...
if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) {
if (!can_replace) {
collection::const_iterator pos = m_values.find(key);
if (pos != m_values.end())
return false;
}
m_values[key] = value_sp;
return true;
}
return false;
}
bool OptionValueDictionary::DeleteValueForKey(const ConstString &key) {
collection::iterator pos = m_values.find(key);
if (pos != m_values.end()) {
m_values.erase(pos);
return true;
}
return false;
}
lldb::OptionValueSP OptionValueDictionary::DeepCopy() const {
OptionValueDictionary *copied_dict =
new OptionValueDictionary(m_type_mask, m_raw_value_dump);
lldb::OptionValueSP copied_value_sp(copied_dict);
collection::const_iterator pos, end = m_values.end();
for (pos = m_values.begin(); pos != end; ++pos) {
StreamString strm;
strm.Printf("%s=", pos->first.GetCString());
copied_dict->SetValueForKey(pos->first, pos->second->DeepCopy(), true);
}
return copied_value_sp;
}