Reimplemented the code that backed the "settings" in lldb. There were many issues with the previous implementation:
- no setting auto completion
- very manual and error prone way of getting/setting variables
- tons of code duplication
- useless instance names for processes, threads

Now settings can easily be defined like option values. The new settings makes use of the "OptionValue" classes so we can re-use the option value code that we use to set settings in command options. No more instances, just "does the right thing".



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162366 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Interpreter/OptionValueArray.cpp b/source/Interpreter/OptionValueArray.cpp
new file mode 100644
index 0000000..fbddd7b
--- /dev/null
+++ b/source/Interpreter/OptionValueArray.cpp
@@ -0,0 +1,350 @@
+//===-- OptionValueArray.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/OptionValueArray.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+    const Type array_element_type = ConvertTypeMaskToType (m_type_mask);
+    if (dump_mask & eDumpOptionType)
+    {
+        if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
+            strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type));
+        else
+            strm.Printf ("(%s)", GetTypeAsCString());
+    }
+    if (dump_mask & eDumpOptionValue)
+    {
+        if (dump_mask & eDumpOptionType)
+            strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : "");
+        strm.IndentMore();
+        const uint32_t size = m_values.size();
+        for (uint32_t i = 0; i<size; ++i)
+        {
+            strm.Indent();
+            strm.Printf("[%u]: ", i);
+            const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
+            switch (array_element_type)
+            {
+                default:
+                case eTypeArray:
+                case eTypeDictionary:
+                case eTypeProperties:
+                case eTypeFileSpecList:
+                case eTypePathMap:
+                    m_values[i]->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
+                    m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
+                    break;
+            }
+            if (i < (size - 1))
+                strm.EOL();
+        }
+        strm.IndentLess();
+    }
+}
+
+Error
+OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op)
+{
+    Args args(value);
+    return SetArgs (args, op);
+}
+
+
+lldb::OptionValueSP
+OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx,
+                               const char *name,
+                               bool will_modify,
+                               Error &error) const
+{
+    if (name && name[0] == '[')
+    {
+        const char *end_bracket = strchr (name+1, ']');
+        if (end_bracket)
+        {
+            const char *sub_value = NULL;
+            if (end_bracket[1])
+                sub_value = end_bracket + 1;
+            std::string index_str (name+1, end_bracket);
+            const size_t array_count = m_values.size();
+            int32_t idx = Args::StringToSInt32(index_str.c_str(), INT32_MAX, 0, NULL);
+            if (idx != INT32_MAX)
+            {
+                ;
+                uint32_t new_idx = UINT32_MAX;
+                if (idx < 0)
+                {
+                    // Access from the end of the array if the index is negative
+                    new_idx = array_count - idx;
+                }
+                else
+                {
+                    // Just a standard index
+                    new_idx = idx;
+                }
+
+                if (new_idx < array_count)
+                {
+                    if (m_values[new_idx])
+                    {
+                        if (sub_value)
+                            return m_values[new_idx]->GetSubValue (exe_ctx, sub_value, will_modify, error);
+                        else
+                            return m_values[new_idx];
+                    }
+                }
+                else
+                {
+                    if (array_count == 0)
+                        error.SetErrorStringWithFormat("index %i is not valid for an empty array", idx);
+                    else if (idx > 0)
+                        error.SetErrorStringWithFormat("index %i out of range, valid values are 0 through %zu", idx, array_count - 1);
+                    else
+                        error.SetErrorStringWithFormat("negative index %i out of range, valid values are -1 through -%zu", idx, array_count);
+                }
+            }
+        }
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("invalid value path '%s', %s values only support '[<index>]' subvalues where <index> is a positive or negative array index", name, GetTypeAsCString());
+    }
+    return OptionValueSP();
+}
+
+
+size_t
+OptionValueArray::GetArgs (Args &args) const
+{
+    const uint32_t size = m_values.size();
+    std::vector<const char *> argv;
+    for (uint32_t i = 0; i<size; ++i)
+    {
+        const char *string_value = m_values[i]->GetStringValue ();
+        if (string_value)
+            argv.push_back(string_value);
+    }
+    
+    if (argv.empty())
+        args.Clear();
+    else
+        args.SetArguments(argv.size(), &argv[0]);
+    return args.GetArgumentCount();
+}
+
+Error
+OptionValueArray::SetArgs (const Args &args, VarSetOperationType op)
+{
+    Error error;
+    const size_t argc = args.GetArgumentCount();
+    switch (op)
+    {
+    case eVarSetOperationInvalid:
+        error.SetErrorString("unsupported operation");
+        break;
+        
+    case eVarSetOperationInsertBefore:
+    case eVarSetOperationInsertAfter:
+        if (argc > 1)
+        {
+            uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+            const uint32_t count = GetSize();
+            if (idx > count)
+            {
+                error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count);
+            }
+            else
+            {
+                if (op == eVarSetOperationInsertAfter)
+                    ++idx;
+                for (size_t i=1; i<argc; ++i, ++idx)
+                {
+                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
+                                                                                     m_type_mask,
+                                                                                     error));
+                    if (value_sp)
+                    {
+                        if (error.Fail())
+                            return error;
+                        if (idx >= m_values.size())
+                            m_values.push_back(value_sp);
+                        else
+                            m_values.insert(m_values.begin() + idx, value_sp);
+                    }
+                    else
+                    {
+                        error.SetErrorString("array of complex types must subclass OptionValueArray");
+                        return error;
+                    }
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorString("insert operation takes an array index followed by one or more values");
+        }
+        break;
+        
+    case eVarSetOperationRemove:
+        if (argc > 0)
+        {
+            const uint32_t size = m_values.size();
+            std::vector<int> remove_indexes;
+            bool all_indexes_valid = true;
+            size_t i;
+            for (i=0; i<argc; ++i)
+            {
+                const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
+                if (idx >= size)
+                {
+                    all_indexes_valid = false;
+                    break;
+                }
+                else
+                    remove_indexes.push_back(idx);
+            }
+            
+            if (all_indexes_valid)
+            {
+                size_t num_remove_indexes = remove_indexes.size();
+                if (num_remove_indexes)
+                {
+                    // Sort and then erase in reverse so indexes are always valid
+                    if (num_remove_indexes > 1)
+                    {
+                        std::sort(remove_indexes.begin(), remove_indexes.end());
+                        for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos)
+                        {
+                            m_values.erase(m_values.begin() + *pos);
+                        }
+                    }
+                    else
+                    {
+                        // Only one index
+                        m_values.erase(m_values.begin() + remove_indexes.front());
+                    }
+                }
+            }
+            else
+            {
+                error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
+            }
+        }
+        else
+        {
+            error.SetErrorString("remove operation takes one or more array indices");
+        }
+        break;
+        
+    case eVarSetOperationClear:
+        Clear ();
+        break;
+        
+    case eVarSetOperationReplace:
+        if (argc > 1)
+        {
+            uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+            const uint32_t count = GetSize();
+            if (idx > count)
+            {
+                error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count);
+            }
+            else
+            {
+                for (size_t i=1; i<argc; ++i, ++idx)
+                {
+                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
+                                                                                     m_type_mask,
+                                                                                     error));
+                    if (value_sp)
+                    {
+                        if (error.Fail())
+                            return error;
+                        if (idx < count)
+                            m_values[idx] = value_sp;
+                        else
+                            m_values.push_back(value_sp);
+                    }
+                    else
+                    {
+                        error.SetErrorString("array of complex types must subclass OptionValueArray");
+                        return error;
+                    }
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorString("replace operation takes an array index followed by one or more values");
+        }
+        break;
+        
+    case eVarSetOperationAssign:
+        m_values.clear();
+        // Fall through to append case
+    case eVarSetOperationAppend:
+        for (size_t i=0; i<argc; ++i)
+        {
+            lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
+                                                                             m_type_mask,
+                                                                             error));
+            if (value_sp)
+            {
+                if (error.Fail())
+                    return error;
+                m_value_was_set = true;
+                AppendValue(value_sp);
+            }
+            else
+            {
+                error.SetErrorString("array of complex types must subclass OptionValueArray");
+            }
+        }
+        break;
+    }
+    return error;
+}
+
+lldb::OptionValueSP
+OptionValueArray::DeepCopy () const
+{
+    OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump);
+    lldb::OptionValueSP copied_value_sp(copied_array);
+    const uint32_t size = m_values.size();
+    for (uint32_t i = 0; i<size; ++i)
+    {
+        copied_array->AppendValue (m_values[i]->DeepCopy());
+    }
+    return copied_value_sp;
+}
+
+
+