Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convenience methods as discussed in #84 #86

Merged
merged 3 commits into from
Jul 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions src/IniFileParser.Tests/Unit/Model/INIDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,100 @@ public void check_add_keydata_method_using_key_and_value_strings()

Assert.That(newData["newSection"]["newKey1"], Is.EqualTo("value1"));
}

[Test, Description("Tests preconditions for TryGetKey")]
public void TryGetKey_preconditions()
{
var data = new IniDataParser().Parse("");
var separator = data.Configuration.SectionKeySeparator;
string result;

// ensure that various good keys aren't rejected
var goodKey = "";
Assert.DoesNotThrow(() => data.TryGetKey(goodKey, out result));
goodKey = "key";
Assert.DoesNotThrow(() => data.TryGetKey(goodKey, out result));
goodKey = string.Format("section{0}key", separator);
Assert.DoesNotThrow(() => data.TryGetKey(goodKey, out result));

// should be rejected
var badKey = string.Format("section{0}subsection{0}key", separator);
Assert.Throws<ArgumentException>(() => data.TryGetKey(badKey, out result));
}

[Test, Description("Tests retrieving data with TryGetKey")]
public void TryGetKey_data_retrieval()
{
var input = @"
global = 1
[section1]
key1 = 2

[section1\subsection]
key2 = 3
";
var data = new IniDataParser().Parse(input);
var separator = data.Configuration.SectionKeySeparator;
string key;
string result;

// keys should all be retrieved
Assert.IsTrue(data.TryGetKey("global", out result));
Assert.AreEqual(result, "1");

key = string.Format("section1{0}key1", separator);
Assert.IsTrue(data.TryGetKey(key, out result));
Assert.AreEqual(result, "2");

key = string.Format(@"section1\subsection{0}key2", separator);
Assert.IsTrue(data.TryGetKey(key, out result));
Assert.AreEqual(result, "3");

// invalid keys should fail...
Assert.IsFalse(data.TryGetKey(null, out result));
Assert.That(result, Is.Empty);

Assert.IsFalse(data.TryGetKey("", out result));
Assert.That(result, Is.Empty);

Assert.IsFalse(data.TryGetKey("badglobal", out result));
Assert.That(result, Is.Empty);

key = string.Format("badsection{0}badkey", separator);
Assert.IsFalse(data.TryGetKey(key, out result));
Assert.That(result, Is.Empty);
}

// GetKey shares preconditions with TryGetKey, so tests are not duplicated
[Test, Description("Tests retrieving data with GetKey")]
public void GeyKey_data_retrieval()
{
var input = @"
global = 1
[section]
key = 2
";
var data = new IniDataParser().Parse(input);
var separator = data.Configuration.SectionKeySeparator;
string key;

// should succeed
key = "global";
Assert.AreEqual(data.GetKey(key), "1");

key = string.Format("section{0}key", separator);
Assert.AreEqual(data.GetKey(key), "2");

// should fail
key = null;
Assert.IsNull(data.GetKey(key));

key = "badglobal";
Assert.IsNull(data.GetKey(key));

key = string.Format("badsection{0}badkey", separator);
Assert.IsNull(data.GetKey(key));
}
}
}

14 changes: 13 additions & 1 deletion src/IniFileParser/Model/Configuration/IniParserConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public IniParserConfiguration()
AllowDuplicateSections = false;
ThrowExceptionsOnError = true;
SkipInvalidLines = false;
SectionKeySeparator = ':';
}

/// <summary>
Expand All @@ -77,7 +78,9 @@ public IniParserConfiguration(IniParserConfiguration ori)
CommentString = ori.CommentString;
ThrowExceptionsOnError = ori.ThrowExceptionsOnError;

// Regex values should recreate themselves.
SectionKeySeparator = ori.SectionKeySeparator;

// Regex values should recreate themselves.
}
#endregion

Expand Down Expand Up @@ -251,6 +254,15 @@ public string CommentString

public bool SkipInvalidLines { get; set; }

/// <summary>
/// Used to mark the separation between the section name and the key name
/// when using <see cref="IniData.TryGetKey"/>.
/// </summary>
/// <remarks>
/// Defaults to ':'.
/// </remarks>
public char SectionKeySeparator { get; set; }

#endregion

#region Fields
Expand Down
73 changes: 73 additions & 0 deletions src/IniFileParser/Model/IniData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Net;
using IniParser.Model.Configuration;
using IniParser.Model.Formatting;

Expand Down Expand Up @@ -171,6 +172,78 @@ public void Merge(IniData toMergeIniData)

}

/// <summary>
/// Attempts to retrieve a key, using a single string combining section and
/// key name.
/// </summary>
/// <param name="key">
/// The section and key name to retrieve, separated by <see cref="IniParserConfiguration.SectionKeySeparator"/>.
///
/// If key contains no separator, it is treated as a key in the <see cref="Global"/> section.
///
/// Key may contain no more than one separator character.
/// </param>
/// <param name="value">
/// If true is returned, is set to the value retrieved. Otherwise, is set
/// to an empty string.
/// </param>
/// <returns>
/// True if key was found, otherwise false.
/// </returns>
/// <exception cref="ArgumentException">
/// key contained multiple separators.
/// </exception>
public bool TryGetKey(string key, out string value)
{
value = string.Empty;
if (string.IsNullOrEmpty(key)) return false;

var splitKey = key.Split(Configuration.SectionKeySeparator);
var separatorCount = splitKey.Length - 1;
if (separatorCount > 1)
throw new ArgumentException("key contains multiple separators", "key");

if (separatorCount == 0)
{
if (!Global.ContainsKey(key)) return false;

value = Global[key];
return true;
}

var section = splitKey[0];
key = splitKey[1];

if (!_sections.ContainsSection(section)) return false;
var sectionData = _sections[section];
if (!sectionData.ContainsKey(key)) return false;

value = sectionData[key];
return true;
}

/// <summary>
/// Retrieves a key using a single input string combining section and key name.
/// </summary>
/// <param name="key">
/// The section and key name to retrieve, separated by <see cref="IniParserConfiguration.SectionKeySeparator"/>.
///
/// If key contains no separator, it is treated as a key in the <see cref="Global"/> section.
///
/// Key may contain no more than one separator character.
/// </param>
/// <returns>
/// The key's value if it was found, otherwise null.
/// </returns>
/// <exception cref="ArgumentException">
/// key contained multiple separators.
/// </exception>
public string GetKey(string key)
{
string result;
return TryGetKey(key, out result) ? result : null;
}

/// <summary>
/// Merge the sections into this by overwriting this sections.
/// </summary>
Expand Down