diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp new file mode 100644 index 0000000..61f8aba --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp @@ -0,0 +1,436 @@ +//===-- 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/lldb-python.h" + +#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 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(NULL, 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()) + { + 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 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::SetValueFromCString (NULL, op); + break; + } + return error; +} + +Error +OptionValueDictionary::SetValueFromCString (const char *value_cstr, VarSetOperationType op) +{ + Args args(value_cstr); + return SetArgs (args, op); +} + +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 = NULL; + ConstString key; + const char *open_bracket = ::strchr (name, '['); + + if (open_bracket) + { + const char *key_start = open_bracket + 1; + const char *key_end = NULL; + 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() == NULL) + { + error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimitted 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->SetValueFromCString(value, op); + else + { + if (error.AsCString() == NULL) + 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 NULL; +} + + +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->SetValueFromCString(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; +} + |