/// <summary> /// Reads the valueless key. /// </summary> /// <param name="currentSection">The current section.</param> /// <param name="currentLine">The current line.</param> /// <param name="lineRaw">The line raw.</param> /// <param name="lineNumber">The line number.</param> private void ReadValuelessKey(ref ConfigSection currentSection, ref ConfigLine currentLine, string lineRaw, int lineNumber) { if (null != currentLine) { BackupCurrentLine(ref currentSection, ref currentLine, lineNumber); } currentLine = new ConfigKeyValue <object>(lineRaw, Settings.KeyValueSeparator, null, lineNumber); }
/// <summary> /// Reads the empty line. /// </summary> /// <param name="currentLine">The current line.</param> /// <param name="currentSection">The current section.</param> /// <param name="lineRaw">The line raw.</param> /// <param name="lineNumber">The line number.</param> /// <exception cref="ConfigParserException"></exception> private void ReadEmptyLine(ref ConfigSection currentSection, ref ConfigLine currentLine, string lineRaw, int lineNumber) { if (null != currentLine) { BackupCurrentLine(ref currentSection, ref currentLine, lineNumber); } currentLine = new ConfigLine(lineNumber, lineRaw); }
/// <summary> /// Gets the line number of the given line. /// </summary> /// <returns>The line number.</returns> /// <param name="line">Line.</param> internal int GetLineNumber(ConfigLine line) { if (line == null) { throw new ArgumentNullException(nameof(line)); } return((lines == null || !lines.Any()) ? -1 : lines.IndexOf(line)); }
/// <summary> /// Appends the value to key. /// </summary> /// <param name="currentSection">The current section.</param> /// <param name="currentLine">The current line.</param> /// <param name="lineRaw">The line raw.</param> /// <param name="lineNumber">The line number.</param> /// <exception cref="NotImplementedException"></exception> private void AppendValueToKey(ref ConfigSection currentSection, ref ConfigLine currentLine, string lineRaw, int lineNumber) { if (MultiLineValues.NotAllowed == Settings.MultiLineValues || Settings.MultiLineValues.HasFlag(MultiLineValues.NotAllowed)) { throw new ConfigParserException( "Multi-line values are explicitly disallowed by parser settings. Please consider changing them.", lineNumber); } ReadKeyAndValue(ref currentSection, ref currentLine, lineRaw, lineNumber, true); }
/// <summary> /// Reads the comment. /// </summary> /// <param name="currentSection">The current section.</param> /// <param name="currentLine">The current line.</param> /// <param name="lineRaw">The line raw.</param> /// <param name="lineNumber">The line number.</param> private void ReadComment(ref ConfigSection currentSection, ref ConfigLine currentLine, string lineRaw, int lineNumber) { if (null != currentLine) { BackupCurrentLine(ref currentSection, ref currentLine, lineNumber); } var commentMatch = Settings.CommentMatcher.Match(lineRaw); var delimiter = commentMatch.Groups["delimiter"]?.Value; var comment = commentMatch.Groups["comment"]?.Value; currentLine = new ConfigComment(delimiter, comment, lineNumber); }
/// <summary> /// Backups the current line. /// </summary> /// <param name="currentSection">The current section.</param> /// <param name="currentLine">The current line.</param> /// <param name="lineNumber">The line number.</param> /// <exception cref="ConfigParserException">This key value pair is orphan, all the keys must be preceded by a section.</exception> private void BackupCurrentLine(ref ConfigSection currentSection, ref ConfigLine currentLine, int lineNumber) { if (null == currentSection) { if (currentLine is IConfigKeyValue && !Settings.MultiLineValues.HasFlag(MultiLineValues.AllowEmptyTopSection)) { throw new ConfigParserException( "This key value pair is orphan, all the keys must be preceded by a section.", lineNumber); } fileHeader.AddLine(currentLine); currentLine = null; return; } currentSection.AddLine(currentLine); currentLine = null; }
/// <summary> /// Reads the section. /// </summary> /// <param name="currentSection">The current section.</param> /// <param name="currentLine">The current line.</param> /// <param name="lineRaw">The line raw.</param> /// <param name="lineNumber">The line number.</param> private void ReadSection(ref ConfigSection currentSection, ref ConfigLine currentLine, string lineRaw, int lineNumber) { if (null != currentLine) { BackupCurrentLine(ref currentSection, ref currentLine, lineNumber); } if (null != currentSection) { sections.Add(currentSection.SectionName, currentSection); } var sectionMatch = ConfigParserSettings.SectionMatcher.Match(lineRaw); var sectionName = sectionMatch.Groups["name"]?.Value; var indentation = sectionMatch.Groups["indentation"]?.Value; var comment = sectionMatch.Groups["comment"]?.Value; currentSection = new ConfigSection(sectionName, lineNumber, indentation, comment); }
/// <summary> /// Reads the key and value. /// </summary> /// <param name="currentSection">The current section.</param> /// <param name="currentLine">The current line.</param> /// <param name="lineRaw">The line raw.</param> /// <param name="lineNumber">The line number.</param> /// <param name="append">if set to <c>true</c> [append].</param> /// <exception cref="ConfigParserException">Arrays must start from a new line and not after the key! /// or</exception> /// <exception cref="NotImplementedException"></exception> private void ReadKeyAndValue(ref ConfigSection currentSection, ref ConfigLine currentLine, string lineRaw, int lineNumber, bool append = false) { if (null != currentLine && !append) { BackupCurrentLine(ref currentSection, ref currentLine, lineNumber); } if (append && null == currentLine) { throw new ConfigParserException("You are trying to append value to a null line!", lineNumber); } var keyMatch = Settings.KeyMatcher.Match(lineRaw); var keyName = keyMatch.Groups["key"]?.Value; var separator = (string.IsNullOrWhiteSpace(keyMatch.Groups["separator"]?.Value)) ? Settings.KeyValueSeparator : keyMatch.Groups["separator"]?.Value; if (keyMatch.Success && keyMatch.Captures.Count > 0) { lineRaw = lineRaw.Substring(keyMatch.Captures[0].Value.Length); } var valueMatch = Settings.ValueMatcher.Match(lineRaw); var value = valueMatch.Groups["value"]?.Value; switch (Settings.MultiLineValues) { case var _ when Settings.MultiLineValues.HasFlag(MultiLineValues.QuoteDelimitedValues): if (!string.IsNullOrEmpty(value)) { if (Equals('"', value.First())) { value = value.Substring(1); } if (Equals('"', value.Last())) { value = value.Remove(value.Length - 1); } } break; case var _ when Settings.MultiLineValues.HasFlag(MultiLineValues.NotAllowed) || Settings.MultiLineValues.HasFlag(MultiLineValues.Simple): // Do nothing add with quotes if any break; default: throw new ConfigParserException("Unknown key=value situation detected!", lineNumber); } if (append) { currentLine.Content = $"{currentLine.Content}{Settings.NewLine}{value}"; } else { currentLine = new ConfigKeyValue <object>(keyName, separator, value, lineNumber); } }
/// <summary> /// Reads the specified configuration content. /// </summary> /// <param name="configContent">Content of the configuration.</param> /// <exception cref="ArgumentException">configContent</exception> private void Read(string configContent) { if (string.IsNullOrWhiteSpace(configContent)) { throw new ArgumentException(nameof(configContent)); } using (var stringReader = new StringReader(configContent)) { string lineRaw; var lineNumber = 0; ConfigSection currentSection = null; ConfigLine currentLine = null; while (null != (lineRaw = stringReader.ReadLine())) { lineNumber++; switch (lineRaw) { case var _ when string.IsNullOrWhiteSpace(lineRaw): ReadEmptyLine(ref currentSection, ref currentLine, lineRaw, lineNumber); continue; case var _ when ConfigParserSettings.SectionMatcher.IsMatch(lineRaw): ReadSection(ref currentSection, ref currentLine, lineRaw, lineNumber); break; case var _ when Settings.CommentMatcher.IsMatch(lineRaw): ReadComment(ref currentSection, ref currentLine, lineRaw, lineNumber); break; case var _ when Settings.KeyMatcher.IsMatch(lineRaw): ReadKeyAndValue(ref currentSection, ref currentLine, lineRaw, lineNumber); break; // Multi-line + allow value-less option on case var _ when Settings.ValueMatcher.IsMatch(lineRaw) && currentLine != null && Settings.KeyMatcher.IsMatch(currentLine.ToString()) && Settings.MultiLineValues.HasFlag(MultiLineValues.AllowValuelessKeys) && Settings.MultiLineValues.HasFlag(MultiLineValues.Simple) && ConfigLine.IndentationMatcher.IsMatch(lineRaw) && !Equals(currentLine.Indentation, ConfigLine.IndentationMatcher.Match(lineRaw).Value): AppendValueToKey(ref currentSection, ref currentLine, lineRaw, lineNumber); break; case var _ when Settings.ValueMatcher.IsMatch(lineRaw): if (Settings.MultiLineValues.HasFlag(MultiLineValues.AllowValuelessKeys)) { ReadValuelessKey(ref currentSection, ref currentLine, lineRaw, lineNumber); } else { AppendValueToKey(ref currentSection, ref currentLine, lineRaw, lineNumber); } break; default: throw new ConfigParserException("Unknown element found!", lineNumber); } } if (null != currentLine) { BackupCurrentLine(ref currentSection, ref currentLine, lineNumber); } if (null != currentSection) { sections.Add(currentSection.SectionName, currentSection); } } }
/// <summary> /// Adds a configuration file line. /// </summary> /// <param name="configLine">The configuration file line to add.</param> internal override void AddLine(ConfigLine configLine) { base.AddLine(configLine); configLine.Section = this; }
/// <summary> /// Adds a configuration file line. /// </summary> /// <param name="configLine">The configuration file line to add.</param> protected internal void AddLine(ConfigLine configLine) { lines.Add(configLine); configLine.Section = this; }
/// <summary> /// Adds a configuration file line. /// </summary> /// <param name="configLine">The configuration file line to add.</param> internal virtual void AddLine(ConfigLine configLine) { lines.Add(configLine); }