summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp436
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;
+}
+
OpenPOWER on IntegriCloud