1254721Semaste//===-- OptionValuePathMappings.cpp -----------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Interpreter/OptionValuePathMappings.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/Core/Stream.h"
17254721Semaste#include "lldb/Interpreter/Args.h"
18254721Semaste
19254721Semasteusing namespace lldb;
20254721Semasteusing namespace lldb_private;
21254721Semaste
22254721Semastevoid
23254721SemasteOptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
24254721Semaste{
25254721Semaste    if (dump_mask & eDumpOptionType)
26254721Semaste        strm.Printf ("(%s)", GetTypeAsCString ());
27254721Semaste    if (dump_mask & eDumpOptionValue)
28254721Semaste    {
29254721Semaste        if (dump_mask & eDumpOptionType)
30254721Semaste            strm.Printf (" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
31254721Semaste        m_path_mappings.Dump(&strm);
32254721Semaste    }
33254721Semaste}
34254721Semaste
35254721SemasteError
36254721SemasteOptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperationType op)
37254721Semaste{
38254721Semaste    Error error;
39254721Semaste    Args args(value);
40254721Semaste    const size_t argc = args.GetArgumentCount();
41254721Semaste
42254721Semaste    switch (op)
43254721Semaste    {
44254721Semaste        case eVarSetOperationClear:
45254721Semaste            Clear ();
46254721Semaste            break;
47254721Semaste
48254721Semaste        case eVarSetOperationReplace:
49254721Semaste            // Must be at least one index + 1 pair of paths, and the pair count must be even
50254721Semaste            if (argc >= 3 && (((argc - 1) & 1) == 0))
51254721Semaste            {
52254721Semaste                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
53254721Semaste                const uint32_t count = m_path_mappings.GetSize();
54254721Semaste                if (idx > count)
55254721Semaste                {
56254721Semaste                    error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
57254721Semaste                }
58254721Semaste                else
59254721Semaste                {
60254721Semaste                    for (size_t i=1; i<argc; i += 2, ++idx)
61254721Semaste                    {
62254721Semaste                        ConstString a(args.GetArgumentAtIndex(i));
63254721Semaste                        ConstString b(args.GetArgumentAtIndex(i+1));
64254721Semaste                        if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
65254721Semaste                            m_path_mappings.Append(a, b, m_notify_changes);
66254721Semaste                    }
67254721Semaste                }
68254721Semaste            }
69254721Semaste            else
70254721Semaste            {
71254721Semaste                error.SetErrorString("replace operation takes an array index followed by one or more path pairs");
72254721Semaste            }
73254721Semaste            break;
74254721Semaste
75254721Semaste
76254721Semaste
77254721Semaste        case eVarSetOperationAssign:
78254721Semaste            if (argc < 2 || (argc & 1))
79254721Semaste            {
80254721Semaste                error.SetErrorString("assign operation takes one or more path pairs");
81254721Semaste                break;
82254721Semaste            }
83254721Semaste            m_path_mappings.Clear(m_notify_changes);
84254721Semaste            // Fall through to append case
85254721Semaste        case eVarSetOperationAppend:
86254721Semaste            if (argc < 2 || (argc & 1))
87254721Semaste            {
88254721Semaste                error.SetErrorString("append operation takes one or more path pairs");
89254721Semaste                break;
90254721Semaste            }
91254721Semaste            else
92254721Semaste            {
93254721Semaste                for (size_t i=0; i<argc; i += 2)
94254721Semaste                {
95254721Semaste                    ConstString a(args.GetArgumentAtIndex(i));
96254721Semaste                    ConstString b(args.GetArgumentAtIndex(i+1));
97254721Semaste                    m_path_mappings.Append(a, b, m_notify_changes);
98254721Semaste                    m_value_was_set = true;
99254721Semaste                }
100254721Semaste            }
101254721Semaste            break;
102254721Semaste
103254721Semaste        case eVarSetOperationInsertBefore:
104254721Semaste        case eVarSetOperationInsertAfter:
105254721Semaste            // Must be at least one index + 1 pair of paths, and the pair count must be even
106254721Semaste            if (argc >= 3 && (((argc - 1) & 1) == 0))
107254721Semaste            {
108254721Semaste                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
109254721Semaste                const uint32_t count = m_path_mappings.GetSize();
110254721Semaste                if (idx > count)
111254721Semaste                {
112254721Semaste                    error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
113254721Semaste                }
114254721Semaste                else
115254721Semaste                {
116254721Semaste                    if (op == eVarSetOperationInsertAfter)
117254721Semaste                        ++idx;
118254721Semaste                    for (size_t i=1; i<argc; i += 2, ++idx)
119254721Semaste                    {
120254721Semaste                        ConstString a(args.GetArgumentAtIndex(i));
121254721Semaste                        ConstString b(args.GetArgumentAtIndex(i+1));
122254721Semaste                        m_path_mappings.Insert (a, b, idx, m_notify_changes);
123254721Semaste                    }
124254721Semaste                }
125254721Semaste            }
126254721Semaste            else
127254721Semaste            {
128254721Semaste                error.SetErrorString("insert operation takes an array index followed by one or more path pairs");
129254721Semaste            }
130254721Semaste            break;
131254721Semaste
132254721Semaste        case eVarSetOperationRemove:
133254721Semaste            if (argc > 0)
134254721Semaste            {
135254721Semaste                std::vector<int> remove_indexes;
136254721Semaste                bool all_indexes_valid = true;
137254721Semaste                size_t i;
138254721Semaste                for (i=0; all_indexes_valid && i<argc; ++i)
139254721Semaste                {
140254721Semaste                    const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
141254721Semaste                    if (idx == INT32_MAX)
142254721Semaste                        all_indexes_valid = false;
143254721Semaste                    else
144254721Semaste                        remove_indexes.push_back(idx);
145254721Semaste                }
146254721Semaste
147254721Semaste                if (all_indexes_valid)
148254721Semaste                {
149254721Semaste                    size_t num_remove_indexes = remove_indexes.size();
150254721Semaste                    if (num_remove_indexes)
151254721Semaste                    {
152254721Semaste                        // Sort and then erase in reverse so indexes are always valid
153254721Semaste                        std::sort(remove_indexes.begin(), remove_indexes.end());
154254721Semaste                        for (size_t j=num_remove_indexes-1; j<num_remove_indexes; ++j)
155254721Semaste                        {
156254721Semaste                            m_path_mappings.Remove (j, m_notify_changes);
157254721Semaste                        }
158254721Semaste                    }
159254721Semaste                }
160254721Semaste                else
161254721Semaste                {
162254721Semaste                    error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
163254721Semaste                }
164254721Semaste            }
165254721Semaste            else
166254721Semaste            {
167254721Semaste                error.SetErrorString("remove operation takes one or more array index");
168254721Semaste            }
169254721Semaste            break;
170254721Semaste
171254721Semaste        case eVarSetOperationInvalid:
172254721Semaste            error = OptionValue::SetValueFromCString (value, op);
173254721Semaste            break;
174254721Semaste    }
175254721Semaste    return error;
176254721Semaste
177254721Semaste    m_value_was_set = true;
178254721Semaste    return Error();
179254721Semaste}
180254721Semaste
181254721Semastelldb::OptionValueSP
182254721SemasteOptionValuePathMappings::DeepCopy () const
183254721Semaste{
184254721Semaste    return OptionValueSP(new OptionValuePathMappings(*this));
185254721Semaste}
186