1//===-- OptionValuePathMappings.cpp -----------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Interpreter/OptionValuePathMappings.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Stream.h"
17#include "lldb/Interpreter/Args.h"
18
19using namespace lldb;
20using namespace lldb_private;
21
22void
23OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
24{
25    if (dump_mask & eDumpOptionType)
26        strm.Printf ("(%s)", GetTypeAsCString ());
27    if (dump_mask & eDumpOptionValue)
28    {
29        if (dump_mask & eDumpOptionType)
30            strm.Printf (" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
31        m_path_mappings.Dump(&strm);
32    }
33}
34
35Error
36OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperationType op)
37{
38    Error error;
39    Args args(value);
40    const size_t argc = args.GetArgumentCount();
41
42    switch (op)
43    {
44        case eVarSetOperationClear:
45            Clear ();
46            break;
47
48        case eVarSetOperationReplace:
49            // Must be at least one index + 1 pair of paths, and the pair count must be even
50            if (argc >= 3 && (((argc - 1) & 1) == 0))
51            {
52                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
53                const uint32_t count = m_path_mappings.GetSize();
54                if (idx > count)
55                {
56                    error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
57                }
58                else
59                {
60                    for (size_t i=1; i<argc; i += 2, ++idx)
61                    {
62                        ConstString a(args.GetArgumentAtIndex(i));
63                        ConstString b(args.GetArgumentAtIndex(i+1));
64                        if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
65                            m_path_mappings.Append(a, b, m_notify_changes);
66                    }
67                }
68            }
69            else
70            {
71                error.SetErrorString("replace operation takes an array index followed by one or more path pairs");
72            }
73            break;
74
75
76
77        case eVarSetOperationAssign:
78            if (argc < 2 || (argc & 1))
79            {
80                error.SetErrorString("assign operation takes one or more path pairs");
81                break;
82            }
83            m_path_mappings.Clear(m_notify_changes);
84            // Fall through to append case
85        case eVarSetOperationAppend:
86            if (argc < 2 || (argc & 1))
87            {
88                error.SetErrorString("append operation takes one or more path pairs");
89                break;
90            }
91            else
92            {
93                for (size_t i=0; i<argc; i += 2)
94                {
95                    ConstString a(args.GetArgumentAtIndex(i));
96                    ConstString b(args.GetArgumentAtIndex(i+1));
97                    m_path_mappings.Append(a, b, m_notify_changes);
98                    m_value_was_set = true;
99                }
100            }
101            break;
102
103        case eVarSetOperationInsertBefore:
104        case eVarSetOperationInsertAfter:
105            // Must be at least one index + 1 pair of paths, and the pair count must be even
106            if (argc >= 3 && (((argc - 1) & 1) == 0))
107            {
108                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
109                const uint32_t count = m_path_mappings.GetSize();
110                if (idx > count)
111                {
112                    error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
113                }
114                else
115                {
116                    if (op == eVarSetOperationInsertAfter)
117                        ++idx;
118                    for (size_t i=1; i<argc; i += 2, ++idx)
119                    {
120                        ConstString a(args.GetArgumentAtIndex(i));
121                        ConstString b(args.GetArgumentAtIndex(i+1));
122                        m_path_mappings.Insert (a, b, idx, m_notify_changes);
123                    }
124                }
125            }
126            else
127            {
128                error.SetErrorString("insert operation takes an array index followed by one or more path pairs");
129            }
130            break;
131
132        case eVarSetOperationRemove:
133            if (argc > 0)
134            {
135                std::vector<int> remove_indexes;
136                bool all_indexes_valid = true;
137                size_t i;
138                for (i=0; all_indexes_valid && i<argc; ++i)
139                {
140                    const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
141                    if (idx == INT32_MAX)
142                        all_indexes_valid = false;
143                    else
144                        remove_indexes.push_back(idx);
145                }
146
147                if (all_indexes_valid)
148                {
149                    size_t num_remove_indexes = remove_indexes.size();
150                    if (num_remove_indexes)
151                    {
152                        // Sort and then erase in reverse so indexes are always valid
153                        std::sort(remove_indexes.begin(), remove_indexes.end());
154                        for (size_t j=num_remove_indexes-1; j<num_remove_indexes; ++j)
155                        {
156                            m_path_mappings.Remove (j, m_notify_changes);
157                        }
158                    }
159                }
160                else
161                {
162                    error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
163                }
164            }
165            else
166            {
167                error.SetErrorString("remove operation takes one or more array index");
168            }
169            break;
170
171        case eVarSetOperationInvalid:
172            error = OptionValue::SetValueFromCString (value, op);
173            break;
174    }
175    return error;
176
177    m_value_was_set = true;
178    return Error();
179}
180
181lldb::OptionValueSP
182OptionValuePathMappings::DeepCopy () const
183{
184    return OptionValueSP(new OptionValuePathMappings(*this));
185}
186