diff options
Diffstat (limited to 'source/Interpreter/OptionValueDictionary.cpp')
| -rw-r--r-- | source/Interpreter/OptionValueDictionary.cpp | 640 | 
1 files changed, 259 insertions, 381 deletions
| diff --git a/source/Interpreter/OptionValueDictionary.cpp b/source/Interpreter/OptionValueDictionary.cpp index 24eeec3b3285..dfba435603bb 100644 --- a/source/Interpreter/OptionValueDictionary.cpp +++ b/source/Interpreter/OptionValueDictionary.cpp @@ -22,423 +22,301 @@  using namespace lldb;  using namespace lldb_private; -void -OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ -    const Type dict_type = ConvertTypeMaskToType (m_type_mask); +void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx, +                                      Stream &strm, uint32_t dump_mask) { +  const Type dict_type = ConvertTypeMaskToType(m_type_mask); +  if (dump_mask & eDumpOptionType) { +    if (m_type_mask != eTypeInvalid) +      strm.Printf("(%s of %ss)", GetTypeAsCString(), +                  GetBuiltinTypeAsCString(dict_type)); +    else +      strm.Printf("(%s)", GetTypeAsCString()); +  } +  if (dump_mask & eDumpOptionValue) {      if (dump_mask & eDumpOptionType) -    { -        if (m_type_mask != eTypeInvalid) -            strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(dict_type)); -        else -            strm.Printf ("(%s)", GetTypeAsCString()); -    } -    if (dump_mask & eDumpOptionValue) -    { -        if (dump_mask & eDumpOptionType) -            strm.PutCString (" ="); - -        collection::iterator pos, end = m_values.end(); - -        strm.IndentMore(); -         -        for (pos = m_values.begin(); pos != end; ++pos) -        { -            OptionValue *option_value = pos->second.get(); -            strm.EOL(); -            strm.Indent(pos->first.GetCString()); -             -            const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; -            switch (dict_type) -            { -                default: -                case eTypeArray: -                case eTypeDictionary: -                case eTypeProperties: -                case eTypeFileSpecList: -                case eTypePathMap: -                    strm.PutChar (' '); -                    option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); -                    break; +      strm.PutCString(" ="); -                case eTypeBoolean: -                case eTypeChar: -                case eTypeEnum: -                case eTypeFileSpec: -                case eTypeFormat: -                case eTypeSInt64: -                case eTypeString: -                case eTypeUInt64: -                case eTypeUUID: -                    // No need to show the type for dictionaries of simple items -                    strm.PutCString("="); -                    option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options); -                    break; -            } -        } -        strm.IndentLess(); -    } +    collection::iterator pos, end = m_values.end(); -} +    strm.IndentMore(); -size_t -OptionValueDictionary::GetArgs (Args &args) const -{ -    args.Clear(); -    collection::const_iterator pos, end = m_values.end(); -    for (pos = m_values.begin(); pos != end; ++pos) -    { -        StreamString strm; -        strm.Printf("%s=", pos->first.GetCString()); -        pos->second->DumpValue(nullptr, strm, eDumpOptionValue|eDumpOptionRaw); -        args.AppendArgument(strm.GetString().c_str()); -    } -    return args.GetArgumentCount(); -} +    for (pos = m_values.begin(); pos != end; ++pos) { +      OptionValue *option_value = pos->second.get(); +      strm.EOL(); +      strm.Indent(pos->first.GetCString()); -Error -OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op) -{ -    Error error; -    const size_t argc = args.GetArgumentCount(); -    switch (op) -    { -    case eVarSetOperationClear: -        Clear(); +      const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; +      switch (dict_type) { +      default: +      case eTypeArray: +      case eTypeDictionary: +      case eTypeProperties: +      case eTypeFileSpecList: +      case eTypePathMap: +        strm.PutChar(' '); +        option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);          break; -         -    case eVarSetOperationAppend: -    case eVarSetOperationReplace: -    case eVarSetOperationAssign: -        if (argc > 0) -        { -            for (size_t i=0; i<argc; ++i) -            { -                llvm::StringRef key_and_value(args.GetArgumentAtIndex(i)); -                if (!key_and_value.empty()) -                { -                    if (key_and_value.find('=') == llvm::StringRef::npos) -                    { -                        error.SetErrorString("assign operation takes one or more key=value arguments"); -                        return error; -                    } - -                    std::pair<llvm::StringRef, llvm::StringRef> kvp(key_and_value.split('=')); -                    llvm::StringRef key = kvp.first; -                    bool key_valid = false; -                    if (!key.empty()) -                    { -                        if (key.front() == '[') -                        { -                            // Key name starts with '[', so the key value must be in single or double quotes like: -                            // ['<key>'] -                            // ["<key>"] -                            if ((key.size() > 2) && (key.back() == ']')) -                            { -                                // Strip leading '[' and trailing ']' -                                key = key.substr(1, key.size()-2); -                                const char quote_char = key.front(); -                                if ((quote_char == '\'') || (quote_char == '"')) -                                { -                                    if ((key.size() > 2) && (key.back() == quote_char)) -                                    { -                                        // Strip the quotes -                                        key = key.substr(1, key.size()-2); -                                        key_valid = true; -                                    } -                                } -                                else -                                { -                                    // square brackets, no quotes -                                    key_valid = true; -                                } -                            } -                        } -                        else -                        { -                            // No square brackets or quotes -                            key_valid = true; -                        } -                    } -                    if (!key_valid) -                    { -                        error.SetErrorStringWithFormat("invalid key \"%s\", the key must be a bare string or surrounded by brackets with optional quotes: [<key>] or ['<key>'] or [\"<key>\"]", kvp.first.str().c_str()); -                        return error; -                    } -                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (kvp.second.data(), -                                                                                     m_type_mask, -                                                                                     error)); -                    if (value_sp) -                    { -                        if (error.Fail()) -                            return error; -                        m_value_was_set = true; -                        SetValueForKey (ConstString(key), value_sp, true); -                    } -                    else -                    { -                        error.SetErrorString("dictionaries that can contain multiple types must subclass OptionValueArray"); -                    } -                } -                else -                { -                    error.SetErrorString("empty argument"); -                } -            } -        } -        else -        { -            error.SetErrorString("assign operation takes one or more key=value arguments"); -        } -        break; -         -    case eVarSetOperationRemove: -        if (argc > 0) -        { -            for (size_t i=0; i<argc; ++i) -            { -                ConstString key(args.GetArgumentAtIndex(i)); -                if (!DeleteValueForKey(key)) -                { -                    error.SetErrorStringWithFormat("no value found named '%s', aborting remove operation", key.GetCString()); -                    break; -                } -            } -        } -        else -        { -            error.SetErrorString("remove operation takes one or more key arguments"); -        } -        break; -         -    case eVarSetOperationInsertBefore: -    case eVarSetOperationInsertAfter: -    case eVarSetOperationInvalid: -        error = OptionValue::SetValueFromString (llvm::StringRef(), op); +      case eTypeBoolean: +      case eTypeChar: +      case eTypeEnum: +      case eTypeFileSpec: +      case eTypeFormat: +      case eTypeSInt64: +      case eTypeString: +      case eTypeUInt64: +      case eTypeUUID: +        // No need to show the type for dictionaries of simple items +        strm.PutCString("="); +        option_value->DumpValue(exe_ctx, strm, +                                (dump_mask & (~eDumpOptionType)) | +                                    extra_dump_options);          break; +      }      } -    return error; +    strm.IndentLess(); +  }  } -Error -OptionValueDictionary::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ -    Args args(value.str().c_str()); -    Error error = SetArgs (args, op); -    if (error.Success()) -        NotifyValueChanged(); -    return error; +size_t OptionValueDictionary::GetArgs(Args &args) const { +  args.Clear(); +  collection::const_iterator pos, end = m_values.end(); +  for (pos = m_values.begin(); pos != end; ++pos) { +    StreamString strm; +    strm.Printf("%s=", pos->first.GetCString()); +    pos->second->DumpValue(nullptr, strm, eDumpOptionValue | eDumpOptionRaw); +    args.AppendArgument(strm.GetString()); +  } +  return args.GetArgumentCount();  } -lldb::OptionValueSP -OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char *name, bool will_modify, Error &error) const -{ -    lldb::OptionValueSP value_sp; +Error OptionValueDictionary::SetArgs(const Args &args, VarSetOperationType op) { +  Error error; +  const size_t argc = args.GetArgumentCount(); +  switch (op) { +  case eVarSetOperationClear: +    Clear(); +    break; -    if (name && name[0]) -    { -        const char *sub_name = nullptr; -        ConstString key; -        const char *open_bracket = ::strchr (name, '['); +  case eVarSetOperationAppend: +  case eVarSetOperationReplace: +  case eVarSetOperationAssign: +    if (argc == 0) { +      error.SetErrorString( +          "assign operation takes one or more key=value arguments"); +      return error; +    } +    for (const auto &entry : args) { +      if (entry.ref.empty()) { +        error.SetErrorString("empty argument"); +        return error; +      } +      if (!entry.ref.contains('=')) { +        error.SetErrorString( +            "assign operation takes one or more key=value arguments"); +        return error; +      } -        if (open_bracket) -        { -            const char *key_start = open_bracket + 1; -            const char *key_end = nullptr; -            switch (open_bracket[1]) -            { -                case '\'': -                    ++key_start; -                    key_end = strchr(key_start, '\''); -                    if (key_end) -                    { -                        if (key_end[1] == ']') -                        { -                            if (key_end[2]) -                                sub_name = key_end + 2; -                        } -                        else -                        { -                            error.SetErrorStringWithFormat ("invalid value path '%s', single quoted key names must be formatted as ['<key>'] where <key> is a string that doesn't contain quotes", name); -                            return value_sp; -                        } -                    } -                    else -                    { -                        error.SetErrorString ("missing '] key name terminator, key name started with ['"); -                        return value_sp; -                    } -                    break; -                case '"': -                    ++key_start; -                    key_end = strchr(key_start, '"'); -                    if (key_end) -                    { -                        if (key_end[1] == ']') -                        { -                            if (key_end[2]) -                                sub_name = key_end + 2; -                            break; -                        } -                        error.SetErrorStringWithFormat ("invalid value path '%s', double quoted key names must be formatted as [\"<key>\"] where <key> is a string that doesn't contain quotes", name); -                        return value_sp; -                    } -                    else -                    { -                        error.SetErrorString ("missing \"] key name terminator, key name started with [\""); -                        return value_sp; -                    } -                    break; +      llvm::StringRef key, value; +      std::tie(key, value) = entry.ref.split('='); +      bool key_valid = false; +      if (key.empty()) { +        error.SetErrorString("empty dictionary key"); +        return error; +      } -                default: -                    key_end = strchr(key_start, ']'); -                    if (key_end) -                    { -                        if (key_end[1]) -                            sub_name = key_end + 1; -                    } -                    else -                    { -                        error.SetErrorString ("missing ] key name terminator, key name started with ["); -                        return value_sp; -                    } -                    break; +      if (key.front() == '[') { +        // Key name starts with '[', so the key value must be in single or +        // double quotes like: +        // ['<key>'] +        // ["<key>"] +        if ((key.size() > 2) && (key.back() == ']')) { +          // Strip leading '[' and trailing ']' +          key = key.substr(1, key.size() - 2); +          const char quote_char = key.front(); +          if ((quote_char == '\'') || (quote_char == '"')) { +            if ((key.size() > 2) && (key.back() == quote_char)) { +              // Strip the quotes +              key = key.substr(1, key.size() - 2); +              key_valid = true;              } -             -            if (key_start && key_end) -            { -                key.SetCStringWithLength (key_start, key_end - key_start); -         -                value_sp = GetValueForKey (key); -                if (value_sp) -                { -                    if (sub_name) -                        return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error); -                } -                else -                { -                    error.SetErrorStringWithFormat("dictionary does not contain a value for the key name '%s'", key.GetCString()); -                } -            } -        } -        if (!value_sp && error.AsCString() == nullptr) -        { -            error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimited by single or double quotes", -                                            name, -                                            GetTypeAsCString()); +          } else { +            // square brackets, no quotes +            key_valid = true; +          }          } +      } else { +        // No square brackets or quotes +        key_valid = true; +      } +      if (!key_valid) { +        error.SetErrorStringWithFormat( +            "invalid key \"%s\", the key must be a bare string or " +            "surrounded by brackets with optional quotes: [<key>] or " +            "['<key>'] or [\"<key>\"]", +            key.str().c_str()); +        return error; +      } + +      lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask( +          value.str().c_str(), m_type_mask, error)); +      if (value_sp) { +        if (error.Fail()) +          return error; +        m_value_was_set = true; +        SetValueForKey(ConstString(key), value_sp, true); +      } else { +        error.SetErrorString("dictionaries that can contain multiple types " +                             "must subclass OptionValueArray"); +      }      } -    return value_sp; -} +    break; -Error -OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOperationType op, const char *name, const char *value) -{ -    Error error; -    const bool will_modify = true; -    lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); -    if (value_sp) -        error = value_sp->SetValueFromString(value, op); -    else -    { -        if (error.AsCString() == nullptr) -            error.SetErrorStringWithFormat("invalid value path '%s'", name); +  case eVarSetOperationRemove: +    if (argc > 0) { +      for (size_t i = 0; i < argc; ++i) { +        ConstString key(args.GetArgumentAtIndex(i)); +        if (!DeleteValueForKey(key)) { +          error.SetErrorStringWithFormat( +              "no value found named '%s', aborting remove operation", +              key.GetCString()); +          break; +        } +      } +    } else { +      error.SetErrorString("remove operation takes one or more key arguments");      } -    return error; +    break; + +  case eVarSetOperationInsertBefore: +  case eVarSetOperationInsertAfter: +  case eVarSetOperationInvalid: +    error = OptionValue::SetValueFromString(llvm::StringRef(), op); +    break; +  } +  return error;  } +Error OptionValueDictionary::SetValueFromString(llvm::StringRef value, +                                                VarSetOperationType op) { +  Args args(value.str()); +  Error error = SetArgs(args, op); +  if (error.Success()) +    NotifyValueChanged(); +  return error; +}  lldb::OptionValueSP -OptionValueDictionary::GetValueForKey (const ConstString &key) const -{ -    lldb::OptionValueSP value_sp; -    collection::const_iterator pos = m_values.find (key); -    if (pos != m_values.end()) -        value_sp = pos->second; -    return value_sp; -} +OptionValueDictionary::GetSubValue(const ExecutionContext *exe_ctx, +  llvm::StringRef name, bool will_modify, +                                   Error &error) const { +  lldb::OptionValueSP value_sp; +  if (name.empty()) +    return nullptr; -const char * -OptionValueDictionary::GetStringValueForKey (const ConstString &key) -{ -    collection::const_iterator pos = m_values.find (key); -    if (pos != m_values.end()) -    { -        OptionValueString *string_value = pos->second->GetAsString(); -        if (string_value) -            return string_value->GetCurrentValue(); -    } +  llvm::StringRef left, temp; +  std::tie(left, temp) = name.split('['); +  if (left.size() == name.size()) { +    error.SetErrorStringWithFormat("invalid value path '%s', %s values only " +      "support '[<key>]' subvalues where <key> " +      "a string value optionally delimited by " +      "single or double quotes", +      name.str().c_str(), GetTypeAsCString());      return nullptr; -} +  } +  assert(!temp.empty()); +  llvm::StringRef key, value; +  llvm::StringRef quote_char; -bool -OptionValueDictionary::SetStringValueForKey (const ConstString &key,  -                                             const char *value,  -                                             bool can_replace) -{ -    collection::const_iterator pos = m_values.find (key); -    if (pos != m_values.end()) -    { -        if (!can_replace) -            return false; -        if (pos->second->GetType() == OptionValue::eTypeString) -        { -            pos->second->SetValueFromString(value); -            return true; -        } -    } -    m_values[key] = OptionValueSP (new OptionValueString (value)); -    return true; +  if (temp[0] == '\"' || temp[0] == '\'') { +    quote_char = temp.take_front(); +    temp = temp.drop_front(); +  } -} +  llvm::StringRef sub_name; +  std::tie(key, sub_name) = temp.split(']'); -bool -OptionValueDictionary::SetValueForKey (const ConstString &key,  -                                       const lldb::OptionValueSP &value_sp,  -                                       bool can_replace) -{ -    // Make sure the value_sp object is allowed to contain -    // values of the type passed in... -    if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) -    { -        if (!can_replace) -        { -            collection::const_iterator pos = m_values.find (key); -            if (pos != m_values.end()) -                return false; -        } -        m_values[key] = value_sp; -        return true; -    } -    return false; +  if (!key.consume_back(quote_char) || key.empty()) { +    error.SetErrorStringWithFormat("invalid value path '%s', " +      "key names must be formatted as ['<key>'] where <key> " +      "is a string that doesn't contain quotes and the quote" +      " char is optional", name.str().c_str()); +    return nullptr; +  } + +  value_sp = GetValueForKey(ConstString(key)); +  if (!value_sp) { +    error.SetErrorStringWithFormat( +      "dictionary does not contain a value for the key name '%s'", +      key.str().c_str()); +    return nullptr; +  } + +  if (sub_name.empty()) +    return value_sp; +  return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);  } -bool -OptionValueDictionary::DeleteValueForKey (const ConstString &key) -{ -    collection::iterator pos = m_values.find (key); -    if (pos != m_values.end()) -    { -        m_values.erase(pos); -        return true; -    } -    return false; +Error OptionValueDictionary::SetSubValue(const ExecutionContext *exe_ctx, +                                         VarSetOperationType op, +  llvm::StringRef name, llvm::StringRef value) { +  Error error; +  const bool will_modify = true; +  lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error)); +  if (value_sp) +    error = value_sp->SetValueFromString(value, op); +  else { +    if (error.AsCString() == nullptr) +      error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str()); +  } +  return error;  }  lldb::OptionValueSP -OptionValueDictionary::DeepCopy () const -{ -    OptionValueDictionary *copied_dict = new OptionValueDictionary (m_type_mask, m_raw_value_dump); -    lldb::OptionValueSP copied_value_sp(copied_dict); -    collection::const_iterator pos, end = m_values.end(); -    for (pos = m_values.begin(); pos != end; ++pos) -    { -        StreamString strm; -        strm.Printf("%s=", pos->first.GetCString()); -        copied_dict->SetValueForKey (pos->first, pos->second->DeepCopy(), true); +OptionValueDictionary::GetValueForKey(const ConstString &key) const { +  lldb::OptionValueSP value_sp; +  collection::const_iterator pos = m_values.find(key); +  if (pos != m_values.end()) +    value_sp = pos->second; +  return value_sp; +} + +bool OptionValueDictionary::SetValueForKey(const ConstString &key, +                                           const lldb::OptionValueSP &value_sp, +                                           bool can_replace) { +  // Make sure the value_sp object is allowed to contain +  // values of the type passed in... +  if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) { +    if (!can_replace) { +      collection::const_iterator pos = m_values.find(key); +      if (pos != m_values.end()) +        return false;      } -    return copied_value_sp; +    m_values[key] = value_sp; +    return true; +  } +  return false; +} + +bool OptionValueDictionary::DeleteValueForKey(const ConstString &key) { +  collection::iterator pos = m_values.find(key); +  if (pos != m_values.end()) { +    m_values.erase(pos); +    return true; +  } +  return false;  } +lldb::OptionValueSP OptionValueDictionary::DeepCopy() const { +  OptionValueDictionary *copied_dict = +      new OptionValueDictionary(m_type_mask, m_raw_value_dump); +  lldb::OptionValueSP copied_value_sp(copied_dict); +  collection::const_iterator pos, end = m_values.end(); +  for (pos = m_values.begin(); pos != end; ++pos) { +    StreamString strm; +    strm.Printf("%s=", pos->first.GetCString()); +    copied_dict->SetValueForKey(pos->first, pos->second->DeepCopy(), true); +  } +  return copied_value_sp; +} | 
