1*67cc0636SGreg Clayton //===-- OptionValueArray.cpp ------------------------------------*- C++ -*-===// 2*67cc0636SGreg Clayton // 3*67cc0636SGreg Clayton // The LLVM Compiler Infrastructure 4*67cc0636SGreg Clayton // 5*67cc0636SGreg Clayton // This file is distributed under the University of Illinois Open Source 6*67cc0636SGreg Clayton // License. See LICENSE.TXT for details. 7*67cc0636SGreg Clayton // 8*67cc0636SGreg Clayton //===----------------------------------------------------------------------===// 9*67cc0636SGreg Clayton 10*67cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h" 11*67cc0636SGreg Clayton 12*67cc0636SGreg Clayton // C Includes 13*67cc0636SGreg Clayton // C++ Includes 14*67cc0636SGreg Clayton // Other libraries and framework includes 15*67cc0636SGreg Clayton // Project includes 16*67cc0636SGreg Clayton #include "lldb/Core/Stream.h" 17*67cc0636SGreg Clayton #include "lldb/Interpreter/Args.h" 18*67cc0636SGreg Clayton 19*67cc0636SGreg Clayton using namespace lldb; 20*67cc0636SGreg Clayton using namespace lldb_private; 21*67cc0636SGreg Clayton 22*67cc0636SGreg Clayton void 23*67cc0636SGreg Clayton OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) 24*67cc0636SGreg Clayton { 25*67cc0636SGreg Clayton const Type array_element_type = ConvertTypeMaskToType (m_type_mask); 26*67cc0636SGreg Clayton if (dump_mask & eDumpOptionType) 27*67cc0636SGreg Clayton { 28*67cc0636SGreg Clayton if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid)) 29*67cc0636SGreg Clayton strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type)); 30*67cc0636SGreg Clayton else 31*67cc0636SGreg Clayton strm.Printf ("(%s)", GetTypeAsCString()); 32*67cc0636SGreg Clayton } 33*67cc0636SGreg Clayton if (dump_mask & eDumpOptionValue) 34*67cc0636SGreg Clayton { 35*67cc0636SGreg Clayton if (dump_mask & eDumpOptionType) 36*67cc0636SGreg Clayton strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : ""); 37*67cc0636SGreg Clayton strm.IndentMore(); 38*67cc0636SGreg Clayton const uint32_t size = m_values.size(); 39*67cc0636SGreg Clayton for (uint32_t i = 0; i<size; ++i) 40*67cc0636SGreg Clayton { 41*67cc0636SGreg Clayton strm.Indent(); 42*67cc0636SGreg Clayton strm.Printf("[%u]: ", i); 43*67cc0636SGreg Clayton const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; 44*67cc0636SGreg Clayton switch (array_element_type) 45*67cc0636SGreg Clayton { 46*67cc0636SGreg Clayton default: 47*67cc0636SGreg Clayton case eTypeArray: 48*67cc0636SGreg Clayton case eTypeDictionary: 49*67cc0636SGreg Clayton case eTypeProperties: 50*67cc0636SGreg Clayton case eTypeFileSpecList: 51*67cc0636SGreg Clayton case eTypePathMap: 52*67cc0636SGreg Clayton m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); 53*67cc0636SGreg Clayton break; 54*67cc0636SGreg Clayton 55*67cc0636SGreg Clayton case eTypeBoolean: 56*67cc0636SGreg Clayton case eTypeEnum: 57*67cc0636SGreg Clayton case eTypeFileSpec: 58*67cc0636SGreg Clayton case eTypeFormat: 59*67cc0636SGreg Clayton case eTypeSInt64: 60*67cc0636SGreg Clayton case eTypeString: 61*67cc0636SGreg Clayton case eTypeUInt64: 62*67cc0636SGreg Clayton case eTypeUUID: 63*67cc0636SGreg Clayton // No need to show the type for dictionaries of simple items 64*67cc0636SGreg Clayton m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options); 65*67cc0636SGreg Clayton break; 66*67cc0636SGreg Clayton } 67*67cc0636SGreg Clayton if (i < (size - 1)) 68*67cc0636SGreg Clayton strm.EOL(); 69*67cc0636SGreg Clayton } 70*67cc0636SGreg Clayton strm.IndentLess(); 71*67cc0636SGreg Clayton } 72*67cc0636SGreg Clayton } 73*67cc0636SGreg Clayton 74*67cc0636SGreg Clayton Error 75*67cc0636SGreg Clayton OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op) 76*67cc0636SGreg Clayton { 77*67cc0636SGreg Clayton Args args(value); 78*67cc0636SGreg Clayton return SetArgs (args, op); 79*67cc0636SGreg Clayton } 80*67cc0636SGreg Clayton 81*67cc0636SGreg Clayton 82*67cc0636SGreg Clayton lldb::OptionValueSP 83*67cc0636SGreg Clayton OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx, 84*67cc0636SGreg Clayton const char *name, 85*67cc0636SGreg Clayton bool will_modify, 86*67cc0636SGreg Clayton Error &error) const 87*67cc0636SGreg Clayton { 88*67cc0636SGreg Clayton if (name && name[0] == '[') 89*67cc0636SGreg Clayton { 90*67cc0636SGreg Clayton const char *end_bracket = strchr (name+1, ']'); 91*67cc0636SGreg Clayton if (end_bracket) 92*67cc0636SGreg Clayton { 93*67cc0636SGreg Clayton const char *sub_value = NULL; 94*67cc0636SGreg Clayton if (end_bracket[1]) 95*67cc0636SGreg Clayton sub_value = end_bracket + 1; 96*67cc0636SGreg Clayton std::string index_str (name+1, end_bracket); 97*67cc0636SGreg Clayton const size_t array_count = m_values.size(); 98*67cc0636SGreg Clayton int32_t idx = Args::StringToSInt32(index_str.c_str(), INT32_MAX, 0, NULL); 99*67cc0636SGreg Clayton if (idx != INT32_MAX) 100*67cc0636SGreg Clayton { 101*67cc0636SGreg Clayton ; 102*67cc0636SGreg Clayton uint32_t new_idx = UINT32_MAX; 103*67cc0636SGreg Clayton if (idx < 0) 104*67cc0636SGreg Clayton { 105*67cc0636SGreg Clayton // Access from the end of the array if the index is negative 106*67cc0636SGreg Clayton new_idx = array_count - idx; 107*67cc0636SGreg Clayton } 108*67cc0636SGreg Clayton else 109*67cc0636SGreg Clayton { 110*67cc0636SGreg Clayton // Just a standard index 111*67cc0636SGreg Clayton new_idx = idx; 112*67cc0636SGreg Clayton } 113*67cc0636SGreg Clayton 114*67cc0636SGreg Clayton if (new_idx < array_count) 115*67cc0636SGreg Clayton { 116*67cc0636SGreg Clayton if (m_values[new_idx]) 117*67cc0636SGreg Clayton { 118*67cc0636SGreg Clayton if (sub_value) 119*67cc0636SGreg Clayton return m_values[new_idx]->GetSubValue (exe_ctx, sub_value, will_modify, error); 120*67cc0636SGreg Clayton else 121*67cc0636SGreg Clayton return m_values[new_idx]; 122*67cc0636SGreg Clayton } 123*67cc0636SGreg Clayton } 124*67cc0636SGreg Clayton else 125*67cc0636SGreg Clayton { 126*67cc0636SGreg Clayton if (array_count == 0) 127*67cc0636SGreg Clayton error.SetErrorStringWithFormat("index %i is not valid for an empty array", idx); 128*67cc0636SGreg Clayton else if (idx > 0) 129*67cc0636SGreg Clayton error.SetErrorStringWithFormat("index %i out of range, valid values are 0 through %zu", idx, array_count - 1); 130*67cc0636SGreg Clayton else 131*67cc0636SGreg Clayton error.SetErrorStringWithFormat("negative index %i out of range, valid values are -1 through -%zu", idx, array_count); 132*67cc0636SGreg Clayton } 133*67cc0636SGreg Clayton } 134*67cc0636SGreg Clayton } 135*67cc0636SGreg Clayton } 136*67cc0636SGreg Clayton else 137*67cc0636SGreg Clayton { 138*67cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid value path '%s', %s values only support '[<index>]' subvalues where <index> is a positive or negative array index", name, GetTypeAsCString()); 139*67cc0636SGreg Clayton } 140*67cc0636SGreg Clayton return OptionValueSP(); 141*67cc0636SGreg Clayton } 142*67cc0636SGreg Clayton 143*67cc0636SGreg Clayton 144*67cc0636SGreg Clayton size_t 145*67cc0636SGreg Clayton OptionValueArray::GetArgs (Args &args) const 146*67cc0636SGreg Clayton { 147*67cc0636SGreg Clayton const uint32_t size = m_values.size(); 148*67cc0636SGreg Clayton std::vector<const char *> argv; 149*67cc0636SGreg Clayton for (uint32_t i = 0; i<size; ++i) 150*67cc0636SGreg Clayton { 151*67cc0636SGreg Clayton const char *string_value = m_values[i]->GetStringValue (); 152*67cc0636SGreg Clayton if (string_value) 153*67cc0636SGreg Clayton argv.push_back(string_value); 154*67cc0636SGreg Clayton } 155*67cc0636SGreg Clayton 156*67cc0636SGreg Clayton if (argv.empty()) 157*67cc0636SGreg Clayton args.Clear(); 158*67cc0636SGreg Clayton else 159*67cc0636SGreg Clayton args.SetArguments(argv.size(), &argv[0]); 160*67cc0636SGreg Clayton return args.GetArgumentCount(); 161*67cc0636SGreg Clayton } 162*67cc0636SGreg Clayton 163*67cc0636SGreg Clayton Error 164*67cc0636SGreg Clayton OptionValueArray::SetArgs (const Args &args, VarSetOperationType op) 165*67cc0636SGreg Clayton { 166*67cc0636SGreg Clayton Error error; 167*67cc0636SGreg Clayton const size_t argc = args.GetArgumentCount(); 168*67cc0636SGreg Clayton switch (op) 169*67cc0636SGreg Clayton { 170*67cc0636SGreg Clayton case eVarSetOperationInvalid: 171*67cc0636SGreg Clayton error.SetErrorString("unsupported operation"); 172*67cc0636SGreg Clayton break; 173*67cc0636SGreg Clayton 174*67cc0636SGreg Clayton case eVarSetOperationInsertBefore: 175*67cc0636SGreg Clayton case eVarSetOperationInsertAfter: 176*67cc0636SGreg Clayton if (argc > 1) 177*67cc0636SGreg Clayton { 178*67cc0636SGreg Clayton uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 179*67cc0636SGreg Clayton const uint32_t count = GetSize(); 180*67cc0636SGreg Clayton if (idx > count) 181*67cc0636SGreg Clayton { 182*67cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count); 183*67cc0636SGreg Clayton } 184*67cc0636SGreg Clayton else 185*67cc0636SGreg Clayton { 186*67cc0636SGreg Clayton if (op == eVarSetOperationInsertAfter) 187*67cc0636SGreg Clayton ++idx; 188*67cc0636SGreg Clayton for (size_t i=1; i<argc; ++i, ++idx) 189*67cc0636SGreg Clayton { 190*67cc0636SGreg Clayton lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i), 191*67cc0636SGreg Clayton m_type_mask, 192*67cc0636SGreg Clayton error)); 193*67cc0636SGreg Clayton if (value_sp) 194*67cc0636SGreg Clayton { 195*67cc0636SGreg Clayton if (error.Fail()) 196*67cc0636SGreg Clayton return error; 197*67cc0636SGreg Clayton if (idx >= m_values.size()) 198*67cc0636SGreg Clayton m_values.push_back(value_sp); 199*67cc0636SGreg Clayton else 200*67cc0636SGreg Clayton m_values.insert(m_values.begin() + idx, value_sp); 201*67cc0636SGreg Clayton } 202*67cc0636SGreg Clayton else 203*67cc0636SGreg Clayton { 204*67cc0636SGreg Clayton error.SetErrorString("array of complex types must subclass OptionValueArray"); 205*67cc0636SGreg Clayton return error; 206*67cc0636SGreg Clayton } 207*67cc0636SGreg Clayton } 208*67cc0636SGreg Clayton } 209*67cc0636SGreg Clayton } 210*67cc0636SGreg Clayton else 211*67cc0636SGreg Clayton { 212*67cc0636SGreg Clayton error.SetErrorString("insert operation takes an array index followed by one or more values"); 213*67cc0636SGreg Clayton } 214*67cc0636SGreg Clayton break; 215*67cc0636SGreg Clayton 216*67cc0636SGreg Clayton case eVarSetOperationRemove: 217*67cc0636SGreg Clayton if (argc > 0) 218*67cc0636SGreg Clayton { 219*67cc0636SGreg Clayton const uint32_t size = m_values.size(); 220*67cc0636SGreg Clayton std::vector<int> remove_indexes; 221*67cc0636SGreg Clayton bool all_indexes_valid = true; 222*67cc0636SGreg Clayton size_t i; 223*67cc0636SGreg Clayton for (i=0; i<argc; ++i) 224*67cc0636SGreg Clayton { 225*67cc0636SGreg Clayton const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); 226*67cc0636SGreg Clayton if (idx >= size) 227*67cc0636SGreg Clayton { 228*67cc0636SGreg Clayton all_indexes_valid = false; 229*67cc0636SGreg Clayton break; 230*67cc0636SGreg Clayton } 231*67cc0636SGreg Clayton else 232*67cc0636SGreg Clayton remove_indexes.push_back(idx); 233*67cc0636SGreg Clayton } 234*67cc0636SGreg Clayton 235*67cc0636SGreg Clayton if (all_indexes_valid) 236*67cc0636SGreg Clayton { 237*67cc0636SGreg Clayton size_t num_remove_indexes = remove_indexes.size(); 238*67cc0636SGreg Clayton if (num_remove_indexes) 239*67cc0636SGreg Clayton { 240*67cc0636SGreg Clayton // Sort and then erase in reverse so indexes are always valid 241*67cc0636SGreg Clayton if (num_remove_indexes > 1) 242*67cc0636SGreg Clayton { 243*67cc0636SGreg Clayton std::sort(remove_indexes.begin(), remove_indexes.end()); 244*67cc0636SGreg Clayton for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos) 245*67cc0636SGreg Clayton { 246*67cc0636SGreg Clayton m_values.erase(m_values.begin() + *pos); 247*67cc0636SGreg Clayton } 248*67cc0636SGreg Clayton } 249*67cc0636SGreg Clayton else 250*67cc0636SGreg Clayton { 251*67cc0636SGreg Clayton // Only one index 252*67cc0636SGreg Clayton m_values.erase(m_values.begin() + remove_indexes.front()); 253*67cc0636SGreg Clayton } 254*67cc0636SGreg Clayton } 255*67cc0636SGreg Clayton } 256*67cc0636SGreg Clayton else 257*67cc0636SGreg Clayton { 258*67cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i)); 259*67cc0636SGreg Clayton } 260*67cc0636SGreg Clayton } 261*67cc0636SGreg Clayton else 262*67cc0636SGreg Clayton { 263*67cc0636SGreg Clayton error.SetErrorString("remove operation takes one or more array indices"); 264*67cc0636SGreg Clayton } 265*67cc0636SGreg Clayton break; 266*67cc0636SGreg Clayton 267*67cc0636SGreg Clayton case eVarSetOperationClear: 268*67cc0636SGreg Clayton Clear (); 269*67cc0636SGreg Clayton break; 270*67cc0636SGreg Clayton 271*67cc0636SGreg Clayton case eVarSetOperationReplace: 272*67cc0636SGreg Clayton if (argc > 1) 273*67cc0636SGreg Clayton { 274*67cc0636SGreg Clayton uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 275*67cc0636SGreg Clayton const uint32_t count = GetSize(); 276*67cc0636SGreg Clayton if (idx > count) 277*67cc0636SGreg Clayton { 278*67cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count); 279*67cc0636SGreg Clayton } 280*67cc0636SGreg Clayton else 281*67cc0636SGreg Clayton { 282*67cc0636SGreg Clayton for (size_t i=1; i<argc; ++i, ++idx) 283*67cc0636SGreg Clayton { 284*67cc0636SGreg Clayton lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i), 285*67cc0636SGreg Clayton m_type_mask, 286*67cc0636SGreg Clayton error)); 287*67cc0636SGreg Clayton if (value_sp) 288*67cc0636SGreg Clayton { 289*67cc0636SGreg Clayton if (error.Fail()) 290*67cc0636SGreg Clayton return error; 291*67cc0636SGreg Clayton if (idx < count) 292*67cc0636SGreg Clayton m_values[idx] = value_sp; 293*67cc0636SGreg Clayton else 294*67cc0636SGreg Clayton m_values.push_back(value_sp); 295*67cc0636SGreg Clayton } 296*67cc0636SGreg Clayton else 297*67cc0636SGreg Clayton { 298*67cc0636SGreg Clayton error.SetErrorString("array of complex types must subclass OptionValueArray"); 299*67cc0636SGreg Clayton return error; 300*67cc0636SGreg Clayton } 301*67cc0636SGreg Clayton } 302*67cc0636SGreg Clayton } 303*67cc0636SGreg Clayton } 304*67cc0636SGreg Clayton else 305*67cc0636SGreg Clayton { 306*67cc0636SGreg Clayton error.SetErrorString("replace operation takes an array index followed by one or more values"); 307*67cc0636SGreg Clayton } 308*67cc0636SGreg Clayton break; 309*67cc0636SGreg Clayton 310*67cc0636SGreg Clayton case eVarSetOperationAssign: 311*67cc0636SGreg Clayton m_values.clear(); 312*67cc0636SGreg Clayton // Fall through to append case 313*67cc0636SGreg Clayton case eVarSetOperationAppend: 314*67cc0636SGreg Clayton for (size_t i=0; i<argc; ++i) 315*67cc0636SGreg Clayton { 316*67cc0636SGreg Clayton lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i), 317*67cc0636SGreg Clayton m_type_mask, 318*67cc0636SGreg Clayton error)); 319*67cc0636SGreg Clayton if (value_sp) 320*67cc0636SGreg Clayton { 321*67cc0636SGreg Clayton if (error.Fail()) 322*67cc0636SGreg Clayton return error; 323*67cc0636SGreg Clayton m_value_was_set = true; 324*67cc0636SGreg Clayton AppendValue(value_sp); 325*67cc0636SGreg Clayton } 326*67cc0636SGreg Clayton else 327*67cc0636SGreg Clayton { 328*67cc0636SGreg Clayton error.SetErrorString("array of complex types must subclass OptionValueArray"); 329*67cc0636SGreg Clayton } 330*67cc0636SGreg Clayton } 331*67cc0636SGreg Clayton break; 332*67cc0636SGreg Clayton } 333*67cc0636SGreg Clayton return error; 334*67cc0636SGreg Clayton } 335*67cc0636SGreg Clayton 336*67cc0636SGreg Clayton lldb::OptionValueSP 337*67cc0636SGreg Clayton OptionValueArray::DeepCopy () const 338*67cc0636SGreg Clayton { 339*67cc0636SGreg Clayton OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump); 340*67cc0636SGreg Clayton lldb::OptionValueSP copied_value_sp(copied_array); 341*67cc0636SGreg Clayton const uint32_t size = m_values.size(); 342*67cc0636SGreg Clayton for (uint32_t i = 0; i<size; ++i) 343*67cc0636SGreg Clayton { 344*67cc0636SGreg Clayton copied_array->AppendValue (m_values[i]->DeepCopy()); 345*67cc0636SGreg Clayton } 346*67cc0636SGreg Clayton return copied_value_sp; 347*67cc0636SGreg Clayton } 348*67cc0636SGreg Clayton 349*67cc0636SGreg Clayton 350*67cc0636SGreg Clayton 351