167cc0636SGreg Clayton //===-- OptionValueArray.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/OptionValueArray.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" 175275aaa0SVince 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 OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) 2567cc0636SGreg Clayton { 2667cc0636SGreg Clayton const Type array_element_type = ConvertTypeMaskToType (m_type_mask); 2767cc0636SGreg Clayton if (dump_mask & eDumpOptionType) 2867cc0636SGreg Clayton { 2967cc0636SGreg Clayton if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid)) 3067cc0636SGreg Clayton strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type)); 3167cc0636SGreg Clayton else 3267cc0636SGreg Clayton strm.Printf ("(%s)", GetTypeAsCString()); 3367cc0636SGreg Clayton } 3467cc0636SGreg Clayton if (dump_mask & eDumpOptionValue) 3567cc0636SGreg Clayton { 3667cc0636SGreg Clayton if (dump_mask & eDumpOptionType) 3767cc0636SGreg Clayton strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : ""); 3867cc0636SGreg Clayton strm.IndentMore(); 3967cc0636SGreg Clayton const uint32_t size = m_values.size(); 4067cc0636SGreg Clayton for (uint32_t i = 0; i<size; ++i) 4167cc0636SGreg Clayton { 4267cc0636SGreg Clayton strm.Indent(); 4367cc0636SGreg Clayton strm.Printf("[%u]: ", i); 4467cc0636SGreg Clayton const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; 4567cc0636SGreg Clayton switch (array_element_type) 4667cc0636SGreg Clayton { 4767cc0636SGreg Clayton default: 4867cc0636SGreg Clayton case eTypeArray: 4967cc0636SGreg Clayton case eTypeDictionary: 5067cc0636SGreg Clayton case eTypeProperties: 5167cc0636SGreg Clayton case eTypeFileSpecList: 5267cc0636SGreg Clayton case eTypePathMap: 5367cc0636SGreg Clayton m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); 5467cc0636SGreg Clayton break; 5567cc0636SGreg Clayton 5667cc0636SGreg Clayton case eTypeBoolean: 573e7442b6SZachary Turner case eTypeChar: 5867cc0636SGreg Clayton case eTypeEnum: 5967cc0636SGreg Clayton case eTypeFileSpec: 6067cc0636SGreg Clayton case eTypeFormat: 6167cc0636SGreg Clayton case eTypeSInt64: 6267cc0636SGreg Clayton case eTypeString: 6367cc0636SGreg Clayton case eTypeUInt64: 6467cc0636SGreg Clayton case eTypeUUID: 6567cc0636SGreg Clayton // No need to show the type for dictionaries of simple items 6667cc0636SGreg Clayton m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options); 6767cc0636SGreg Clayton break; 6867cc0636SGreg Clayton } 6967cc0636SGreg Clayton if (i < (size - 1)) 7067cc0636SGreg Clayton strm.EOL(); 7167cc0636SGreg Clayton } 7267cc0636SGreg Clayton strm.IndentLess(); 7367cc0636SGreg Clayton } 7467cc0636SGreg Clayton } 7567cc0636SGreg Clayton 7667cc0636SGreg Clayton Error 7767cc0636SGreg Clayton OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op) 7867cc0636SGreg Clayton { 7967cc0636SGreg Clayton Args args(value); 80*8f37ca56SIlia K Error error = SetArgs (args, op); 81*8f37ca56SIlia K if (error.Success()) 82332e8b1cSGreg Clayton NotifyValueChanged(); 83*8f37ca56SIlia K return error; 8467cc0636SGreg Clayton } 8567cc0636SGreg Clayton 8667cc0636SGreg Clayton 8767cc0636SGreg Clayton lldb::OptionValueSP 8867cc0636SGreg Clayton OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx, 8967cc0636SGreg Clayton const char *name, 9067cc0636SGreg Clayton bool will_modify, 9167cc0636SGreg Clayton Error &error) const 9267cc0636SGreg Clayton { 9367cc0636SGreg Clayton if (name && name[0] == '[') 9467cc0636SGreg Clayton { 9567cc0636SGreg Clayton const char *end_bracket = strchr (name+1, ']'); 9667cc0636SGreg Clayton if (end_bracket) 9767cc0636SGreg Clayton { 98d78c9576SEd Maste const char *sub_value = nullptr; 9967cc0636SGreg Clayton if (end_bracket[1]) 10067cc0636SGreg Clayton sub_value = end_bracket + 1; 10167cc0636SGreg Clayton std::string index_str (name+1, end_bracket); 10267cc0636SGreg Clayton const size_t array_count = m_values.size(); 1035275aaa0SVince Harron int32_t idx = StringConvert::ToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr); 10467cc0636SGreg Clayton if (idx != INT32_MAX) 10567cc0636SGreg Clayton { 10667cc0636SGreg Clayton ; 10767cc0636SGreg Clayton uint32_t new_idx = UINT32_MAX; 10867cc0636SGreg Clayton if (idx < 0) 10967cc0636SGreg Clayton { 11067cc0636SGreg Clayton // Access from the end of the array if the index is negative 11167cc0636SGreg Clayton new_idx = array_count - idx; 11267cc0636SGreg Clayton } 11367cc0636SGreg Clayton else 11467cc0636SGreg Clayton { 11567cc0636SGreg Clayton // Just a standard index 11667cc0636SGreg Clayton new_idx = idx; 11767cc0636SGreg Clayton } 11867cc0636SGreg Clayton 11967cc0636SGreg Clayton if (new_idx < array_count) 12067cc0636SGreg Clayton { 12167cc0636SGreg Clayton if (m_values[new_idx]) 12267cc0636SGreg Clayton { 12367cc0636SGreg Clayton if (sub_value) 12467cc0636SGreg Clayton return m_values[new_idx]->GetSubValue (exe_ctx, sub_value, will_modify, error); 12567cc0636SGreg Clayton else 12667cc0636SGreg Clayton return m_values[new_idx]; 12767cc0636SGreg Clayton } 12867cc0636SGreg Clayton } 12967cc0636SGreg Clayton else 13067cc0636SGreg Clayton { 13167cc0636SGreg Clayton if (array_count == 0) 13267cc0636SGreg Clayton error.SetErrorStringWithFormat("index %i is not valid for an empty array", idx); 13367cc0636SGreg Clayton else if (idx > 0) 134d01b2953SDaniel Malea error.SetErrorStringWithFormat("index %i out of range, valid values are 0 through %" PRIu64, idx, (uint64_t)(array_count - 1)); 13567cc0636SGreg Clayton else 136d01b2953SDaniel Malea error.SetErrorStringWithFormat("negative index %i out of range, valid values are -1 through -%" PRIu64, idx, (uint64_t)array_count); 13767cc0636SGreg Clayton } 13867cc0636SGreg Clayton } 13967cc0636SGreg Clayton } 14067cc0636SGreg Clayton } 14167cc0636SGreg Clayton else 14267cc0636SGreg Clayton { 14367cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid value path '%s', %s values only support '[<index>]' subvalues where <index> is a positive or negative array index", name, GetTypeAsCString()); 14467cc0636SGreg Clayton } 14567cc0636SGreg Clayton return OptionValueSP(); 14667cc0636SGreg Clayton } 14767cc0636SGreg Clayton 14867cc0636SGreg Clayton 14967cc0636SGreg Clayton size_t 15067cc0636SGreg Clayton OptionValueArray::GetArgs (Args &args) const 15167cc0636SGreg Clayton { 15267cc0636SGreg Clayton const uint32_t size = m_values.size(); 15367cc0636SGreg Clayton std::vector<const char *> argv; 15467cc0636SGreg Clayton for (uint32_t i = 0; i<size; ++i) 15567cc0636SGreg Clayton { 15667cc0636SGreg Clayton const char *string_value = m_values[i]->GetStringValue (); 15767cc0636SGreg Clayton if (string_value) 15867cc0636SGreg Clayton argv.push_back(string_value); 15967cc0636SGreg Clayton } 16067cc0636SGreg Clayton 16167cc0636SGreg Clayton if (argv.empty()) 16267cc0636SGreg Clayton args.Clear(); 16367cc0636SGreg Clayton else 16467cc0636SGreg Clayton args.SetArguments(argv.size(), &argv[0]); 16567cc0636SGreg Clayton return args.GetArgumentCount(); 16667cc0636SGreg Clayton } 16767cc0636SGreg Clayton 16867cc0636SGreg Clayton Error 16967cc0636SGreg Clayton OptionValueArray::SetArgs (const Args &args, VarSetOperationType op) 17067cc0636SGreg Clayton { 17167cc0636SGreg Clayton Error error; 17267cc0636SGreg Clayton const size_t argc = args.GetArgumentCount(); 17367cc0636SGreg Clayton switch (op) 17467cc0636SGreg Clayton { 17567cc0636SGreg Clayton case eVarSetOperationInvalid: 17667cc0636SGreg Clayton error.SetErrorString("unsupported operation"); 17767cc0636SGreg Clayton break; 17867cc0636SGreg Clayton 17967cc0636SGreg Clayton case eVarSetOperationInsertBefore: 18067cc0636SGreg Clayton case eVarSetOperationInsertAfter: 18167cc0636SGreg Clayton if (argc > 1) 18267cc0636SGreg Clayton { 1835275aaa0SVince Harron uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 18467cc0636SGreg Clayton const uint32_t count = GetSize(); 18567cc0636SGreg Clayton if (idx > count) 18667cc0636SGreg Clayton { 18767cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count); 18867cc0636SGreg Clayton } 18967cc0636SGreg Clayton else 19067cc0636SGreg Clayton { 19167cc0636SGreg Clayton if (op == eVarSetOperationInsertAfter) 19267cc0636SGreg Clayton ++idx; 19367cc0636SGreg Clayton for (size_t i=1; i<argc; ++i, ++idx) 19467cc0636SGreg Clayton { 19567cc0636SGreg Clayton lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i), 19667cc0636SGreg Clayton m_type_mask, 19767cc0636SGreg Clayton error)); 19867cc0636SGreg Clayton if (value_sp) 19967cc0636SGreg Clayton { 20067cc0636SGreg Clayton if (error.Fail()) 20167cc0636SGreg Clayton return error; 20267cc0636SGreg Clayton if (idx >= m_values.size()) 20367cc0636SGreg Clayton m_values.push_back(value_sp); 20467cc0636SGreg Clayton else 20567cc0636SGreg Clayton m_values.insert(m_values.begin() + idx, value_sp); 20667cc0636SGreg Clayton } 20767cc0636SGreg Clayton else 20867cc0636SGreg Clayton { 20967cc0636SGreg Clayton error.SetErrorString("array of complex types must subclass OptionValueArray"); 21067cc0636SGreg Clayton return error; 21167cc0636SGreg Clayton } 21267cc0636SGreg Clayton } 21367cc0636SGreg Clayton } 21467cc0636SGreg Clayton } 21567cc0636SGreg Clayton else 21667cc0636SGreg Clayton { 21767cc0636SGreg Clayton error.SetErrorString("insert operation takes an array index followed by one or more values"); 21867cc0636SGreg Clayton } 21967cc0636SGreg Clayton break; 22067cc0636SGreg Clayton 22167cc0636SGreg Clayton case eVarSetOperationRemove: 22267cc0636SGreg Clayton if (argc > 0) 22367cc0636SGreg Clayton { 22467cc0636SGreg Clayton const uint32_t size = m_values.size(); 22567cc0636SGreg Clayton std::vector<int> remove_indexes; 22667cc0636SGreg Clayton bool all_indexes_valid = true; 22767cc0636SGreg Clayton size_t i; 22867cc0636SGreg Clayton for (i=0; i<argc; ++i) 22967cc0636SGreg Clayton { 2303985c8c6SSaleem Abdulrasool const size_t idx = 2315275aaa0SVince Harron StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); 23267cc0636SGreg Clayton if (idx >= size) 23367cc0636SGreg Clayton { 23467cc0636SGreg Clayton all_indexes_valid = false; 23567cc0636SGreg Clayton break; 23667cc0636SGreg Clayton } 23767cc0636SGreg Clayton else 23867cc0636SGreg Clayton remove_indexes.push_back(idx); 23967cc0636SGreg Clayton } 24067cc0636SGreg Clayton 24167cc0636SGreg Clayton if (all_indexes_valid) 24267cc0636SGreg Clayton { 24367cc0636SGreg Clayton size_t num_remove_indexes = remove_indexes.size(); 24467cc0636SGreg Clayton if (num_remove_indexes) 24567cc0636SGreg Clayton { 24667cc0636SGreg Clayton // Sort and then erase in reverse so indexes are always valid 24767cc0636SGreg Clayton if (num_remove_indexes > 1) 24867cc0636SGreg Clayton { 24967cc0636SGreg Clayton std::sort(remove_indexes.begin(), remove_indexes.end()); 25067cc0636SGreg Clayton for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos) 25167cc0636SGreg Clayton { 25267cc0636SGreg Clayton m_values.erase(m_values.begin() + *pos); 25367cc0636SGreg Clayton } 25467cc0636SGreg Clayton } 25567cc0636SGreg Clayton else 25667cc0636SGreg Clayton { 25767cc0636SGreg Clayton // Only one index 25867cc0636SGreg Clayton m_values.erase(m_values.begin() + remove_indexes.front()); 25967cc0636SGreg Clayton } 26067cc0636SGreg Clayton } 26167cc0636SGreg Clayton } 26267cc0636SGreg Clayton else 26367cc0636SGreg Clayton { 26467cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i)); 26567cc0636SGreg Clayton } 26667cc0636SGreg Clayton } 26767cc0636SGreg Clayton else 26867cc0636SGreg Clayton { 26967cc0636SGreg Clayton error.SetErrorString("remove operation takes one or more array indices"); 27067cc0636SGreg Clayton } 27167cc0636SGreg Clayton break; 27267cc0636SGreg Clayton 27367cc0636SGreg Clayton case eVarSetOperationClear: 27467cc0636SGreg Clayton Clear (); 27567cc0636SGreg Clayton break; 27667cc0636SGreg Clayton 27767cc0636SGreg Clayton case eVarSetOperationReplace: 27867cc0636SGreg Clayton if (argc > 1) 27967cc0636SGreg Clayton { 2805275aaa0SVince Harron uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 28167cc0636SGreg Clayton const uint32_t count = GetSize(); 28267cc0636SGreg Clayton if (idx > count) 28367cc0636SGreg Clayton { 28467cc0636SGreg Clayton error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count); 28567cc0636SGreg Clayton } 28667cc0636SGreg Clayton else 28767cc0636SGreg Clayton { 28867cc0636SGreg Clayton for (size_t i=1; i<argc; ++i, ++idx) 28967cc0636SGreg Clayton { 29067cc0636SGreg Clayton lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i), 29167cc0636SGreg Clayton m_type_mask, 29267cc0636SGreg Clayton error)); 29367cc0636SGreg Clayton if (value_sp) 29467cc0636SGreg Clayton { 29567cc0636SGreg Clayton if (error.Fail()) 29667cc0636SGreg Clayton return error; 29767cc0636SGreg Clayton if (idx < count) 29867cc0636SGreg Clayton m_values[idx] = value_sp; 29967cc0636SGreg Clayton else 30067cc0636SGreg Clayton m_values.push_back(value_sp); 30167cc0636SGreg Clayton } 30267cc0636SGreg Clayton else 30367cc0636SGreg Clayton { 30467cc0636SGreg Clayton error.SetErrorString("array of complex types must subclass OptionValueArray"); 30567cc0636SGreg Clayton return error; 30667cc0636SGreg Clayton } 30767cc0636SGreg Clayton } 30867cc0636SGreg Clayton } 30967cc0636SGreg Clayton } 31067cc0636SGreg Clayton else 31167cc0636SGreg Clayton { 31267cc0636SGreg Clayton error.SetErrorString("replace operation takes an array index followed by one or more values"); 31367cc0636SGreg Clayton } 31467cc0636SGreg Clayton break; 31567cc0636SGreg Clayton 31667cc0636SGreg Clayton case eVarSetOperationAssign: 31767cc0636SGreg Clayton m_values.clear(); 31867cc0636SGreg Clayton // Fall through to append case 31967cc0636SGreg Clayton case eVarSetOperationAppend: 32067cc0636SGreg Clayton for (size_t i=0; i<argc; ++i) 32167cc0636SGreg Clayton { 32267cc0636SGreg Clayton lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i), 32367cc0636SGreg Clayton m_type_mask, 32467cc0636SGreg Clayton error)); 32567cc0636SGreg Clayton if (value_sp) 32667cc0636SGreg Clayton { 32767cc0636SGreg Clayton if (error.Fail()) 32867cc0636SGreg Clayton return error; 32967cc0636SGreg Clayton m_value_was_set = true; 33067cc0636SGreg Clayton AppendValue(value_sp); 33167cc0636SGreg Clayton } 33267cc0636SGreg Clayton else 33367cc0636SGreg Clayton { 33467cc0636SGreg Clayton error.SetErrorString("array of complex types must subclass OptionValueArray"); 33567cc0636SGreg Clayton } 33667cc0636SGreg Clayton } 33767cc0636SGreg Clayton break; 33867cc0636SGreg Clayton } 33967cc0636SGreg Clayton return error; 34067cc0636SGreg Clayton } 34167cc0636SGreg Clayton 34267cc0636SGreg Clayton lldb::OptionValueSP 34367cc0636SGreg Clayton OptionValueArray::DeepCopy () const 34467cc0636SGreg Clayton { 34567cc0636SGreg Clayton OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump); 34667cc0636SGreg Clayton lldb::OptionValueSP copied_value_sp(copied_array); 347*8f37ca56SIlia K *static_cast<OptionValue *>(copied_array) = *this; 348*8f37ca56SIlia K copied_array->m_callback = m_callback; 34967cc0636SGreg Clayton const uint32_t size = m_values.size(); 35067cc0636SGreg Clayton for (uint32_t i = 0; i<size; ++i) 35167cc0636SGreg Clayton { 35267cc0636SGreg Clayton copied_array->AppendValue (m_values[i]->DeepCopy()); 35367cc0636SGreg Clayton } 35467cc0636SGreg Clayton return copied_value_sp; 35567cc0636SGreg Clayton } 35667cc0636SGreg Clayton 35767cc0636SGreg Clayton 35867cc0636SGreg Clayton 359