Skip to content

Commit

Permalink
partially fixes #17 - Hard to parse redis config file due to non sect…
Browse files Browse the repository at this point in the history
…ion and space separated kv
  • Loading branch information
salaros committed Mar 29, 2021
1 parent 0875582 commit 8b9cff4
Show file tree
Hide file tree
Showing 17 changed files with 360 additions and 174 deletions.
34 changes: 34 additions & 0 deletions src/ConfigParser.NullSection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Linq;

namespace Salaros.Configuration
{
public partial class ConfigParser
{
public class NullConfigSection
{
private ConfigParser parent;

public NullConfigSection(ConfigParser parent)
{
this.parent = parent;
}

public T GetValue<T>(string keyName, T defaultValue = default(T))
{
if (string.IsNullOrWhiteSpace(keyName))
throw new ArgumentException("Key name must be a non-empty string.", nameof(keyName));

var iniKey = new ConfigKeyValue<T>(keyName, parent.Settings.KeyValueSeparator, defaultValue, -1);
var key = parent.fileHeader.Section.Keys.FirstOrDefault(k => Equals(keyName, k.Name));
if (key != null)
return (T)key.ValueRaw;

parent.fileHeader.Section.AddLine(iniKey);
return defaultValue;
}

public string GetValue(string keyName, string defaultValue = null) => GetValue<string>(keyName, defaultValue);
}
}
}
71 changes: 46 additions & 25 deletions src/ConfigParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Salaros.Configuration
{
public class ConfigParser
public partial class ConfigParser
{
private static readonly ILog Logger = LogProvider.GetCurrentClassLogger();
protected readonly ConfigSection fileHeader;
Expand Down Expand Up @@ -48,18 +48,19 @@ static ConfigParser()
public ConfigParser(ConfigParserSettings settings = null)
{
Settings = settings ?? new ConfigParserSettings();
NullSection = new NullConfigSection(this);

fileHeader = new ConfigSection();
sections = new Dictionary<string, ConfigSection>();
}

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:Salaros.Configuration.ConfigParser" /> class.
/// Initializes a new instance of the <see cref="Salaros.Configuration.ConfigParser" /> class.
/// </summary>
/// <param name="configFile">The configuration file (may be path or file content).</param>
/// <param name="settings">The settings.</param>
/// <exception cref="T:System.ArgumentException">configFilePath</exception>
/// <exception cref="System.ArgumentException">configFilePath</exception>
public ConfigParser(string configFile, ConfigParserSettings settings = null)
: this(settings)
{
Expand Down Expand Up @@ -111,16 +112,25 @@ public ConfigParser(string configFile, ConfigParserSettings settings = null)
/// <value>
/// The sections.
/// </value>
public ReadOnlyCollection<ConfigSection> Sections =>
new ReadOnlyCollection<ConfigSection>(sections.Values.ToArray());
#if NET40
public ReadOnlyCollection<ConfigSection> Sections => new ReadOnlyCollection<ConfigSection>(
#else
public IReadOnlyCollection<ConfigSection> Sections => new Collection<ConfigSection>(
#endif
sections.Values.ToList());

/// <summary>
/// Gets configuration file's lines.
/// </summary>
/// <value>The lines.</value>
public ReadOnlyCollection<IConfigLine> Lines
=> new ReadOnlyCollection<IConfigLine>(fileHeader.Lines.Concat(sections.Values.SelectMany(s => s.Lines))
.ToArray());
#if NET40
public ReadOnlyCollection<IConfigLine> Lines => new ReadOnlyCollection<IConfigLine>(
#else
public IReadOnlyCollection<IConfigLine> Lines => new Collection<IConfigLine>(
#endif
fileHeader.Lines.Concat(sections.Values.SelectMany(s => s.Lines)).ToList());

public NullConfigSection NullSection { get; }

#endregion Properties

Expand All @@ -143,19 +153,20 @@ public ReadOnlyCollection<IConfigLine> Lines
/// </exception>
internal virtual bool TryGetValue<T>(string sectionName, string keyName, out T value)
{
if (string.IsNullOrWhiteSpace(sectionName))
if (sectionName is null)
throw new ArgumentNullException(nameof(sectionName));

if (string.IsNullOrWhiteSpace(keyName))
throw new ArgumentNullException(nameof(keyName));
throw new ArgumentException("Key name must be a non-empty string.", nameof(keyName));

#pragma warning disable IDE0034 // Simplify 'default' expression
value = default(T);
#pragma warning restore IDE0034 // Simplify 'default' expression

if (!sections.TryGetValue(sectionName, out var section))
return false;
section = null;

var key = section.Keys.FirstOrDefault(k => Equals(keyName, k.Name));
var key = (section ?? fileHeader?.Section).Keys.FirstOrDefault(k => Equals(keyName, k.Name));
if (key == null)
return false;

Expand All @@ -173,13 +184,13 @@ internal virtual bool TryGetValue<T>(string sectionName, string keyName, out T v
/// <typeparam name="T">The 1st type parameter.</typeparam>
internal virtual T GetRawValue<T>(string sectionName, string keyName, T defaultValue)
{
if (string.IsNullOrWhiteSpace(sectionName))
if (sectionName is null)
throw new ArgumentNullException(nameof(sectionName));

if (string.IsNullOrWhiteSpace(keyName))
throw new ArgumentNullException(nameof(keyName));
throw new ArgumentException("Key name must be a non-empty string.", nameof(keyName));

var iniKey = new ConfigKeyValue<T>(keyName, Settings.KeyValueSeparator, defaultValue, -1);

if (!sections.TryGetValue(sectionName, out var section))
{
section = new ConfigSection(sectionName, Lines.Any() ? Lines.Max(l => l.LineNumber) : 0);
Expand All @@ -188,11 +199,14 @@ internal virtual T GetRawValue<T>(string sectionName, string keyName, T defaultV
sections.Add(sectionName, section);
}

var key = section.Keys.FirstOrDefault(k => Equals(keyName, k.Name));
var key = (section ?? fileHeader?.Section).Keys.FirstOrDefault(k => Equals(keyName, k.Name));
if (key != null)
return (T)key.ValueRaw;

section.AddLine(iniKey);
if (section is null && Settings.MultiLineValues.HasFlag(MultiLineValues.AllowEmptyTopSection))
section = fileHeader.Section;

section?.AddLine(iniKey);
return defaultValue;
}

Expand Down Expand Up @@ -421,7 +435,7 @@ public virtual bool ValueIsArray(string sectionName, string keyName)
return values.Any() && string.IsNullOrWhiteSpace(values.First());
}

#endregion
#endregion

#region SetValue

Expand Down Expand Up @@ -540,7 +554,7 @@ public virtual bool SetValue(string sectionName, string keyName, byte[] value)
return SetValue(sectionName, keyName, EncodeByteArray(value));
}

#endregion
#endregion SetValue

#region Indexing

Expand All @@ -564,7 +578,7 @@ public ConfigSection this[string sectionName]
}
}

#endregion
#endregion Indexing

/// <summary>
/// Save configuration file's content.
Expand Down Expand Up @@ -641,7 +655,7 @@ public override string ToString()
);
}

#endregion
#endregion Methods

#region Helpers

Expand Down Expand Up @@ -819,10 +833,17 @@ private void ReadKeyAndValue(ref ConfigSection currentSection, ref ConfigLine cu
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);
try
{
if (append)
currentLine.Content = $"{currentLine.Content}{Settings.NewLine}{value}";
else
currentLine = new ConfigKeyValue<object>(keyName, separator, value, lineNumber);
}
catch (Exception ex)
{
throw new ConfigParserException($"Failed to parse the following line: '{lineRaw}'", lineNumber, ex);
}
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/ConfigParserException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class ConfigParserException : Exception
{
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:Salaros.Configuration.ConfigParserException" /> class.
/// Initializes a new instance of the <see cref="Salaros.Configuration.ConfigParserException" /> class.
/// </summary>
/// <param name="message">Message.</param>
/// <param name="lineNumber">Line number.</param>
Expand Down
6 changes: 3 additions & 3 deletions src/Entries/ConfigComment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class ConfigComment : ConfigLine

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:IniComment" /> class.
/// Initializes a new instance of the <see cref="IniComment" /> class.
/// </summary>
/// <param name="delimiter">Delimiter.</param>
/// <param name="comment"></param>
Expand Down Expand Up @@ -39,9 +39,9 @@ public string Comment

/// <inheritdoc />
/// <summary>
/// Returns a <see cref="T:System.String" /> that represents the current <see cref="T:Salaros.Config.IniComment" />.
/// Returns a <see cref="System.String" /> that represents the current <see cref="Salaros.Config.IniComment" />.
/// </summary>
/// <returns>A <see cref="T:System.String" /> that represents the current <see cref="T:Salaros.Config.IniComment" />.</returns>
/// <returns>A <see cref="System.String" /> that represents the current <see cref="Salaros.Config.IniComment" />.</returns>
public override string ToString()
{
return (string.IsNullOrWhiteSpace(Comment))
Expand Down
12 changes: 6 additions & 6 deletions src/Entries/ConfigKeyValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ConfigKeyValue<T> : ConfigLine, IConfigKeyValue
#region Constructors

/// <summary>
/// Initializes a new instance of the <see cref="T:Salaros.Config.ConfigKeyValue`T" /> class.
/// Initializes a new instance of the <see cref="Salaros.Config.ConfigKeyValue`T" /> class.
/// </summary>
/// <param name="keyName">Name of the key.</param>
/// <param name="separator">The separator.</param>
Expand All @@ -23,7 +23,7 @@ public ConfigKeyValue(string keyName, string separator, T value, int lineNumber)
if (string.IsNullOrWhiteSpace(keyName))
throw new ArgumentNullException(nameof(keyName));

if (string.IsNullOrWhiteSpace(separator))
if (separator is null)
throw new ArgumentNullException(nameof(separator));

this.keyName = keyName;
Expand Down Expand Up @@ -102,9 +102,9 @@ public override string Content

/// <inheritdoc />
/// <summary>
/// Returns a <see cref="T:string" /> that represents the current <see cref="T:Salaros.Config.ConfigKeyValue" />.
/// Returns a <see cref="string" /> that represents the current <see cref="Salaros.Config.ConfigKeyValue" />.
/// </summary>
/// <returns>A <see cref="T:string" /> that represents the current <see cref="T:Salaros.Config.ConfigKeyValue" />.</returns>
/// <returns>A <see cref="string" /> that represents the current <see cref="Salaros.Config.ConfigKeyValue" />.</returns>
public override string ToString()
{
return ToString(MultiLineValues.NotAllowed);
Expand All @@ -113,11 +113,11 @@ public override string ToString()
/// ReSharper disable once InheritdocInvalidUsage
/// <inheritdoc cref="ConfigLine" />
/// <summary>
/// Returns a <see cref="T:System.String" /> that represents this instance.
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <param name="multiLineSettings">The multi line settings.</param>
/// <returns>
/// A <see cref="T:System.String" /> that represents this instance.
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString(MultiLineValues multiLineSettings)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Entries/ConfigLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ public override string ToString()

/// <inheritdoc />
/// <summary>
/// Returns a <see cref="T:System.String" /> that represents this instance.
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <param name="multiLineSettings">The multi line settings.</param>
/// <returns>
/// A <see cref="T:System.String" /> that represents this instance.
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public virtual string ToString(MultiLineValues multiLineSettings)
{
Expand Down
Loading

0 comments on commit 8b9cff4

Please sign in to comment.