Exemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="IniFile" /> class.
 /// </summary>
 public IniFile()
 {
     GlobalProperties = new IniSection(null);
     Sections         = new IniSectionCollection();
     ErrorLines       = new IniErrorLine[0].ToReadOnlyCollection();
 }
Exemplo n.º 2
0
        /// <summary>
        /// Creates an <see cref="IniFile" /> object from the specified <see cref="Stream" />.
        /// </summary>
        /// <param name="stream">The <see cref="Stream" /> from which to parse the INI file from.</param>
        /// <param name="encoding">The encoding to use to read the file.</param>
        /// <param name="parsingOptions">A <see cref="IniFileParsingOptions" /> object with format specifications for INI parsing, or <see langword="null" /> to use default parsing options.</param>
        /// <param name="leaveOpen">A <see cref="bool" /> value indicating whether to leave <paramref name="stream" /> open.</param>
        /// <returns>
        /// The <see cref="IniFile" /> this method creates.
        /// </returns>
        public static IniFile FromStream(Stream stream, Encoding encoding, IniFileParsingOptions parsingOptions, bool leaveOpen)
        {
            Check.ArgumentNull(stream, nameof(stream));
            Check.ArgumentNull(encoding, nameof(encoding));

            if (parsingOptions == null)
            {
                parsingOptions = new IniFileParsingOptions();
            }

            IniFile             ini           = new IniFile();
            IniSection          section       = ini.GlobalProperties;
            bool                ignoreSection = false;
            List <IniErrorLine> errorLines    = new List <IniErrorLine>();

            using StreamReader reader = new StreamReader(stream, encoding, true, 4096, leaveOpen);

            for (int lineNumber = 1; !reader.EndOfStream; lineNumber++)
            {
                string line        = reader.ReadLine();
                string trimmedLine = line.Trim();

                if (trimmedLine.StartsWith(";") && parsingOptions.AllowSemicolonComments || trimmedLine.StartsWith("#") && parsingOptions.AllowNumberSignComments)
                {
                }
                else if (trimmedLine == "")
                {
                    AbortIf(!parsingOptions.AllowEmptyLines);
                }
                else if (trimmedLine.StartsWith("[") && trimmedLine.EndsWith("]"))
                {
                    string newSection = trimmedLine.Substring(1, trimmedLine.Length - 2);
                    if (parsingOptions.TrimSectionNames)
                    {
                        newSection = newSection.Trim();
                    }
                    AbortIf(!parsingOptions.AllowSectionNameClosingBracket && newSection.Contains("]"));

                    IniSection duplicate = ini.Sections.FirstOrDefault(sect => sect.Name.Equals(newSection, parsingOptions.DuplicateSectionNameIgnoreCase ? SpecialStringComparisons.IgnoreCase : SpecialStringComparisons.None));
                    bool       create    = false;

                    switch (parsingOptions.DuplicateSectionNameBehavior)
                    {
                    case IniDuplicateSectionNameBehavior.Abort:
                        AbortIf(duplicate != null);
                        create = true;
                        break;

                    case IniDuplicateSectionNameBehavior.Ignore:
                        if (duplicate == null)
                        {
                            create = true;
                        }
                        else
                        {
                            ignoreSection = true;
                        }
                        break;

                    case IniDuplicateSectionNameBehavior.Merge:
                        if (duplicate == null)
                        {
                            create = true;
                        }
                        else
                        {
                            section = duplicate;
                        }
                        break;

                    case IniDuplicateSectionNameBehavior.Duplicate:
                        create = true;
                        break;

                    default:
                        throw Throw.InvalidEnumArgument(nameof(parsingOptions.DuplicatePropertyNameBehavior), parsingOptions.DuplicatePropertyNameBehavior);
                    }

                    if (create)
                    {
                        section = new IniSection(newSection);
                        ini.Sections.Add(section);
                    }
                }
                else if (parsingOptions.PropertyDelimiter == IniPropertyDelimiter.EqualSign && line.Contains("="))
                {
                    ParseProperty("=");
                }
                else if (parsingOptions.PropertyDelimiter == IniPropertyDelimiter.Colon && line.Contains(":"))
                {
                    ParseProperty(":");
                }
                else
                {
                    Abort();
                }

                void Abort()
                {
                    if (parsingOptions.IgnoreErrors)
                    {
                        errorLines.Add(new IniErrorLine(lineNumber, line));
                    }
                    else
                    {
                        throw new IniParsingException(lineNumber, line);
                    }
                }

                void AbortIf(bool condition)
                {
                    if (condition)
                    {
                        Abort();
                    }
                }

                void ParseProperty(string delimiter)
                {
                    if (!ignoreSection)
                    {
                        AbortIf(!parsingOptions.AllowGlobalProperties && section == ini.GlobalProperties);

                        IniProperty property = new IniProperty(line.SubstringUntil(delimiter), line.SubstringFrom(delimiter));
                        if (parsingOptions.TrimPropertyNames)
                        {
                            property.Name = property.Name.Trim();
                        }
                        if (parsingOptions.TrimPropertyValues)
                        {
                            property.Value = property.Value.Trim();
                        }

                        IniProperty duplicate = section.Properties.FirstOrDefault(prop => prop.Name.Equals(property.Name, parsingOptions.DuplicatePropertyNameIgnoreCase ? SpecialStringComparisons.IgnoreCase : SpecialStringComparisons.None));
                        if (duplicate == null)
                        {
                            section.Properties.Add(property);
                        }
                        else
                        {
                            switch (parsingOptions.DuplicatePropertyNameBehavior)
                            {
                            case IniDuplicatePropertyNameBehavior.Abort:
                                Abort();
                                break;

                            case IniDuplicatePropertyNameBehavior.Ignore:
                                break;

                            case IniDuplicatePropertyNameBehavior.Overwrite:
                                duplicate.Value = property.Value;
                                break;

                            case IniDuplicatePropertyNameBehavior.Duplicate:
                                section.Properties.Add(property);
                                break;

                            default:
                                throw Throw.InvalidEnumArgument(nameof(parsingOptions.DuplicatePropertyNameBehavior), parsingOptions.DuplicatePropertyNameBehavior);
                            }
                        }
                    }
                }
            }

            ini.ErrorLines = errorLines.AsReadOnly();
            return(ini);
        }