167cc0636SGreg Clayton //===-- OptionValuePathMappings.cpp -----------------------------*- C++ -*-===//
267cc0636SGreg Clayton //
367cc0636SGreg Clayton //                     The LLVM Compiler Infrastructure
467cc0636SGreg Clayton //
567cc0636SGreg Clayton // This file is distributed under the University of Illinois Open Source
667cc0636SGreg Clayton // License. See LICENSE.TXT for details.
767cc0636SGreg Clayton //
867cc0636SGreg Clayton //===----------------------------------------------------------------------===//
967cc0636SGreg Clayton 
1067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValuePathMappings.h"
1167cc0636SGreg Clayton 
1267cc0636SGreg Clayton // C Includes
1367cc0636SGreg Clayton // C++ Includes
1467cc0636SGreg Clayton // Other libraries and framework includes
1567cc0636SGreg Clayton // Project includes
1667cc0636SGreg Clayton #include "lldb/Core/Stream.h"
17*5275aaa0SVince Harron #include "lldb/Host/StringConvert.h"
1867cc0636SGreg Clayton #include "lldb/Interpreter/Args.h"
1967cc0636SGreg Clayton 
2067cc0636SGreg Clayton using namespace lldb;
2167cc0636SGreg Clayton using namespace lldb_private;
2267cc0636SGreg Clayton 
2367cc0636SGreg Clayton void
2467cc0636SGreg Clayton OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
2567cc0636SGreg Clayton {
2667cc0636SGreg Clayton     if (dump_mask & eDumpOptionType)
2767cc0636SGreg Clayton         strm.Printf ("(%s)", GetTypeAsCString ());
2867cc0636SGreg Clayton     if (dump_mask & eDumpOptionValue)
2967cc0636SGreg Clayton     {
3067cc0636SGreg Clayton         if (dump_mask & eDumpOptionType)
3167cc0636SGreg Clayton             strm.Printf (" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
3267cc0636SGreg Clayton         m_path_mappings.Dump(&strm);
3367cc0636SGreg Clayton     }
3467cc0636SGreg Clayton }
3567cc0636SGreg Clayton 
3667cc0636SGreg Clayton Error
3767cc0636SGreg Clayton OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperationType op)
3867cc0636SGreg Clayton {
3967cc0636SGreg Clayton     Error error;
4067cc0636SGreg Clayton     Args args(value);
4167cc0636SGreg Clayton     const size_t argc = args.GetArgumentCount();
4267cc0636SGreg Clayton 
4367cc0636SGreg Clayton     switch (op)
4467cc0636SGreg Clayton     {
4567cc0636SGreg Clayton         case eVarSetOperationClear:
4667cc0636SGreg Clayton             Clear ();
47332e8b1cSGreg Clayton             NotifyValueChanged();
4867cc0636SGreg Clayton             break;
4967cc0636SGreg Clayton 
5067cc0636SGreg Clayton         case eVarSetOperationReplace:
5167cc0636SGreg Clayton             // Must be at least one index + 1 pair of paths, and the pair count must be even
5267cc0636SGreg Clayton             if (argc >= 3 && (((argc - 1) & 1) == 0))
5367cc0636SGreg Clayton             {
54*5275aaa0SVince Harron                 uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
5567cc0636SGreg Clayton                 const uint32_t count = m_path_mappings.GetSize();
5667cc0636SGreg Clayton                 if (idx > count)
5767cc0636SGreg Clayton                 {
5867cc0636SGreg Clayton                     error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
5967cc0636SGreg Clayton                 }
6067cc0636SGreg Clayton                 else
6167cc0636SGreg Clayton                 {
6267cc0636SGreg Clayton                     for (size_t i=1; i<argc; i += 2, ++idx)
6367cc0636SGreg Clayton                     {
6467cc0636SGreg Clayton                         ConstString a(args.GetArgumentAtIndex(i));
6567cc0636SGreg Clayton                         ConstString b(args.GetArgumentAtIndex(i+1));
6667cc0636SGreg Clayton                         if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
6767cc0636SGreg Clayton                             m_path_mappings.Append(a, b, m_notify_changes);
6867cc0636SGreg Clayton                     }
69332e8b1cSGreg Clayton                     NotifyValueChanged();
7067cc0636SGreg Clayton                 }
7167cc0636SGreg Clayton             }
7267cc0636SGreg Clayton             else
7367cc0636SGreg Clayton             {
7467cc0636SGreg Clayton                 error.SetErrorString("replace operation takes an array index followed by one or more path pairs");
7567cc0636SGreg Clayton             }
7667cc0636SGreg Clayton             break;
7767cc0636SGreg Clayton 
7867cc0636SGreg Clayton 
7967cc0636SGreg Clayton 
8067cc0636SGreg Clayton         case eVarSetOperationAssign:
8167cc0636SGreg Clayton             if (argc < 2 || (argc & 1))
8267cc0636SGreg Clayton             {
8367cc0636SGreg Clayton                 error.SetErrorString("assign operation takes one or more path pairs");
8467cc0636SGreg Clayton                 break;
8567cc0636SGreg Clayton             }
8667cc0636SGreg Clayton             m_path_mappings.Clear(m_notify_changes);
8767cc0636SGreg Clayton             // Fall through to append case
8867cc0636SGreg Clayton         case eVarSetOperationAppend:
8967cc0636SGreg Clayton             if (argc < 2 || (argc & 1))
9067cc0636SGreg Clayton             {
9167cc0636SGreg Clayton                 error.SetErrorString("append operation takes one or more path pairs");
9267cc0636SGreg Clayton                 break;
9367cc0636SGreg Clayton             }
9467cc0636SGreg Clayton             else
9567cc0636SGreg Clayton             {
9667cc0636SGreg Clayton                 for (size_t i=0; i<argc; i += 2)
9767cc0636SGreg Clayton                 {
9867cc0636SGreg Clayton                     ConstString a(args.GetArgumentAtIndex(i));
9967cc0636SGreg Clayton                     ConstString b(args.GetArgumentAtIndex(i+1));
10067cc0636SGreg Clayton                     m_path_mappings.Append(a, b, m_notify_changes);
10167cc0636SGreg Clayton                     m_value_was_set = true;
10267cc0636SGreg Clayton                 }
103332e8b1cSGreg Clayton                 NotifyValueChanged();
10467cc0636SGreg Clayton             }
10567cc0636SGreg Clayton             break;
10667cc0636SGreg Clayton 
10767cc0636SGreg Clayton         case eVarSetOperationInsertBefore:
10867cc0636SGreg Clayton         case eVarSetOperationInsertAfter:
10967cc0636SGreg Clayton             // Must be at least one index + 1 pair of paths, and the pair count must be even
11067cc0636SGreg Clayton             if (argc >= 3 && (((argc - 1) & 1) == 0))
11167cc0636SGreg Clayton             {
112*5275aaa0SVince Harron                 uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
11367cc0636SGreg Clayton                 const uint32_t count = m_path_mappings.GetSize();
11467cc0636SGreg Clayton                 if (idx > count)
11567cc0636SGreg Clayton                 {
11667cc0636SGreg Clayton                     error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
11767cc0636SGreg Clayton                 }
11867cc0636SGreg Clayton                 else
11967cc0636SGreg Clayton                 {
12067cc0636SGreg Clayton                     if (op == eVarSetOperationInsertAfter)
12167cc0636SGreg Clayton                         ++idx;
12267cc0636SGreg Clayton                     for (size_t i=1; i<argc; i += 2, ++idx)
12367cc0636SGreg Clayton                     {
12467cc0636SGreg Clayton                         ConstString a(args.GetArgumentAtIndex(i));
12567cc0636SGreg Clayton                         ConstString b(args.GetArgumentAtIndex(i+1));
12667cc0636SGreg Clayton                         m_path_mappings.Insert (a, b, idx, m_notify_changes);
12767cc0636SGreg Clayton                     }
128332e8b1cSGreg Clayton                     NotifyValueChanged();
12967cc0636SGreg Clayton                 }
13067cc0636SGreg Clayton             }
13167cc0636SGreg Clayton             else
13267cc0636SGreg Clayton             {
13367cc0636SGreg Clayton                 error.SetErrorString("insert operation takes an array index followed by one or more path pairs");
13467cc0636SGreg Clayton             }
13567cc0636SGreg Clayton             break;
13667cc0636SGreg Clayton 
13767cc0636SGreg Clayton         case eVarSetOperationRemove:
13867cc0636SGreg Clayton             if (argc > 0)
13967cc0636SGreg Clayton             {
14067cc0636SGreg Clayton                 std::vector<int> remove_indexes;
14167cc0636SGreg Clayton                 bool all_indexes_valid = true;
14267cc0636SGreg Clayton                 size_t i;
14367cc0636SGreg Clayton                 for (i=0; all_indexes_valid && i<argc; ++i)
14467cc0636SGreg Clayton                 {
145*5275aaa0SVince Harron                     const int idx = StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
14667cc0636SGreg Clayton                     if (idx == INT32_MAX)
14767cc0636SGreg Clayton                         all_indexes_valid = false;
14867cc0636SGreg Clayton                     else
14967cc0636SGreg Clayton                         remove_indexes.push_back(idx);
15067cc0636SGreg Clayton                 }
15167cc0636SGreg Clayton 
15267cc0636SGreg Clayton                 if (all_indexes_valid)
15367cc0636SGreg Clayton                 {
15467cc0636SGreg Clayton                     size_t num_remove_indexes = remove_indexes.size();
15567cc0636SGreg Clayton                     if (num_remove_indexes)
15667cc0636SGreg Clayton                     {
15767cc0636SGreg Clayton                         // Sort and then erase in reverse so indexes are always valid
15867cc0636SGreg Clayton                         std::sort(remove_indexes.begin(), remove_indexes.end());
159a297a97eSAndy Gibbs                         for (size_t j=num_remove_indexes-1; j<num_remove_indexes; ++j)
16067cc0636SGreg Clayton                         {
161ccd41e55SJason Molenda                             m_path_mappings.Remove (j, m_notify_changes);
16267cc0636SGreg Clayton                         }
16367cc0636SGreg Clayton                     }
164332e8b1cSGreg Clayton                     NotifyValueChanged();
16567cc0636SGreg Clayton                 }
16667cc0636SGreg Clayton                 else
16767cc0636SGreg Clayton                 {
16867cc0636SGreg Clayton                     error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
16967cc0636SGreg Clayton                 }
17067cc0636SGreg Clayton             }
17167cc0636SGreg Clayton             else
17267cc0636SGreg Clayton             {
17367cc0636SGreg Clayton                 error.SetErrorString("remove operation takes one or more array index");
17467cc0636SGreg Clayton             }
17567cc0636SGreg Clayton             break;
17667cc0636SGreg Clayton 
17767cc0636SGreg Clayton         case eVarSetOperationInvalid:
17867cc0636SGreg Clayton             error = OptionValue::SetValueFromCString (value, op);
17967cc0636SGreg Clayton             break;
18067cc0636SGreg Clayton     }
18167cc0636SGreg Clayton     return error;
18267cc0636SGreg Clayton }
18367cc0636SGreg Clayton 
18467cc0636SGreg Clayton lldb::OptionValueSP
18567cc0636SGreg Clayton OptionValuePathMappings::DeepCopy () const
18667cc0636SGreg Clayton {
18767cc0636SGreg Clayton     return OptionValueSP(new OptionValuePathMappings(*this));
18867cc0636SGreg Clayton }
189