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