/// <summary>
 /// Overriden. <see cref="TypeConverter.ConvertFrom(ITypeDescriptorContext,CultureInfo,object)"/>.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="culture"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
 {
     if (value is string)
     {
         return(IniConfiguration.Parse((string)value));
     }
     return(base.ConvertFrom(context, culture, value));
 }
 /// <summary>
 /// Instantiates a new instance of the <see cref="IniConfiguration"/> class and copy all entries from the specified instance.
 /// </summary>
 /// <param name="other"></param>
 public IniConfiguration(IniConfiguration other)
     : this(other.DefaultSection)
 {
     foreach (IniConfigurationSection e in other)
     {
         BaseAdd(e.Name, new IniConfigurationSection(e));
     }
 }
        /// <summary>
        /// Parse an INI-formatted formatted string and creates a new instance of the <see cref="IniConfiguration"/> class with the parsed keys and values.
        /// </summary>
        /// <param name="data">An INI-formatted formatted string.</param>
        /// <returns>A key-value collection that contains key-value pairs parsed from the specified string.</returns>
        public static IniConfiguration Parse(string data)
        {
            IniConfiguration        iniData        = new IniConfiguration();
            IniConfigurationSection currentSection = iniData.DefaultSection;

            using (StringReader reader = new StringReader(data)) {
                StringBuilder cb = new StringBuilder();
                StringBuilder sb = new StringBuilder();
                while (reader.Peek() > 0)
                {
                    sb.Remove(0, sb.Length);
                    do
                    {
                        string line = reader.ReadLine();
                        if (line.Length > 0)
                        {
                            if (line[line.Length - 1] != '\\')
                            {
                                sb.Append(line);
                                break;
                            }
                            sb.Append(Environment.NewLine);
                            sb.Append(line.Substring(0, line.Length - 1).TrimStart());
                        }
                    } while (reader.Peek() > 0);

                    string entry = sb.ToString().Trim();
                    if (entry.Length == 0)
                    {
                        continue;
                    }
                    if (entry[0] == ';' || entry[0] == '#')
                    {
                        cb.AppendLine(entry.Substring(1));
                    }
                    else if (entry[0] == '[' && entry[entry.Length - 1] == ']')
                    {
                        currentSection = iniData.AddSection(entry.Substring(1, entry.Length - 2));
                        if (cb.Length > 0)
                        {
                            currentSection.SetComment(cb.ToString().TrimEnd());
                        }
                        cb.Remove(0, cb.Length);
                    }
                    else
                    {
                        int equalSignPos = entry.IndexOf('=');
                        if (equalSignPos >= 0)
                        {
                            string key   = entry.Substring(0, equalSignPos).TrimEnd();
                            string value = Regex.Unescape(entry.Substring(equalSignPos + 1).TrimStart());
                            if (value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"')
                            {
                                value = value.Substring(1, value.Length - 2);
                            }
                            currentSection.Add(key, value);
                            if (cb.Length > 0)
                            {
                                currentSection.SetComment(key, cb.ToString().TrimEnd());
                            }
                        }
                        cb.Remove(0, cb.Length);
                    }
                }
                return(iniData);
            }
        }