Skip to content

Commit

Permalink
Merge pull request #20 from lechu445/lb_add_readproperty_method
Browse files Browse the repository at this point in the history
Add IIonReader.ReadProperty() method
  • Loading branch information
wmaryszczak authored Apr 12, 2021
2 parents 7ef9ab3 + 9556683 commit 806cdbf
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 71 deletions.
12 changes: 6 additions & 6 deletions Anixe.Ion.UnitTests/Anixe.Ion.UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
Expand All @@ -9,11 +9,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NSubstitute" Version="3.1.0" />
<PackageReference Include="nunit" Version="3.10.1" />
<PackageReference Include="NUnit.StaticExpect" Version="1.0.7" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NSubstitute" Version="4.2.2" />
<PackageReference Include="nunit" Version="3.13.1" />
<PackageReference Include="NUnit.StaticExpect" Version="2.0.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
</ItemGroup>

<ItemGroup>
Expand Down
50 changes: 50 additions & 0 deletions Anixe.Ion.UnitTests/IonExtensionsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using NUnit.Framework;
using System;
using System.IO;
using System.Text;

namespace Anixe.Ion.UnitTests
{
public class IonExtensionsTest
{
[Test]
public void ReadProperty_Test()
{
var reader = CreateReaderForInput("\"some_key\" = \"some_value\"");
var ionProperty = reader.ReadProperty();

ReadOnlySpan<char> key = ionProperty.Key;
ReadOnlySpan<char> value = ionProperty.Value;

Assert.AreEqual("some_key", key.ToString());
Assert.AreEqual("some_value", value.ToString());

// getting more than one time
Assert.AreEqual("some_key", ionProperty.Key.ToString());

// reading property one more time
var newIonProperty = reader.ReadProperty();
Assert.AreEqual("some_key", newIonProperty.Key.ToString());
}

[Test]
public void ReadProperty_Empty_Property_Test()
{
var reader = CreateReaderForInput("\"\" = \"\"");
var ionProperty = reader.ReadProperty();
Assert.AreEqual("", ionProperty.Key.ToString());
Assert.AreEqual("", ionProperty.Value.ToString());

var secondReader = CreateReaderForInput(" = ");
Assert.AreEqual("", ionProperty.Key.ToString());
Assert.AreEqual("", ionProperty.Value.ToString());
}

private static IIonReader CreateReaderForInput(string input)
{
var reader = IonReaderFactory.Create(new MemoryStream(Encoding.UTF8.GetBytes(input)));
reader.Read();
return reader;
}
}
}
43 changes: 43 additions & 0 deletions Anixe.Ion.UnitTests/IonPropertyTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using NUnit.Framework;
using System;
using System.IO;
using System.Text;

namespace Anixe.Ion.UnitTests
{
public class IonPropertyTest
{
[TestCase("some_key = some_value", "some_key", "some_value")]
[TestCase("\"some_key\" = \"some_value\"", "some_key", "some_value")]
[TestCase("\"some_key\" = 1", "some_key", "1")]
[TestCase(" \"some_key\" = \"some_value\" ", "some_key", "some_value")]
[TestCase("\"some_key\": \"some_value\"", "", "\"some_key\": \"some_value\"")]
[TestCase("\"\" = \"\"", "", "")]
[TestCase(" = ", "", "")]
[TestCase("some key = some value", "some key", "some value")]
[TestCase("key=some=value", "key", "some=value")]
[TestCase("some_setting = \"true\"", "some_setting", "true")]
[TestCase("some_setting =", "some_setting", "")]
public void IonProperty_Test(string input, string key, string value)
{
using var reader = IonReaderFactory.Create(new MemoryStream(Encoding.UTF8.GetBytes(input)));
reader.Read();
Assert.True(reader.IsProperty);

var property = new IonProperty(reader);
Assert.AreEqual(key, property.Key.ToString());
Assert.AreEqual(value, property.Value.ToString());
}

[TestCase("")]
[TestCase("[AAA]")]
[TestCase("|--|--|")]
public void IonProperty_Throws_InvalidOperationException(string input)
{
using var reader = IonReaderFactory.Create(new MemoryStream(Encoding.UTF8.GetBytes(input)));
reader.Read();
Assert.False(reader.IsProperty);
Assert.Throws<InvalidOperationException>(() => new IonProperty(reader));
}
}
}
2 changes: 1 addition & 1 deletion Anixe.Ion/Anixe.Ion.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Version>2.0.18</Version>
<Version>2.1.0</Version>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
30 changes: 15 additions & 15 deletions Anixe.Ion/IIonReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,52 @@ namespace Anixe.Ion
public interface IIonReader : IDisposable
{
/// <summary>
/// Gets a value indicating whether this instance of IonReader is currently on section header.
/// Gets a value indicating whether this instance of <see cref="IIonReader"/> is currently on section header.
/// </summary>
/// <value><c>true</c> if IonReader CurrentLine first character is equal to '['; otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if <see cref="IIonReader.CurrentLine"/> first character is equal to '['; otherwise, <see langword="false"/>.</value>
bool IsSectionHeader { get; }

/// <summary>
/// Gets a value indicating whether this instance of IonReader is currently on property.
/// </summary>
/// <value><c>true</c> if other boolean properties are false; otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if other boolean properties are false; otherwise, <see langword="false"/>.</value>
bool IsProperty { get; }

/// <summary>
/// Gets a value indicating whether this instance of IonReader is currently on comment.
/// </summary>
/// <value><c>true</c> if IonReader CurrentLine first character is equal to '#'; otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if <see cref="IIonReader.CurrentLine"/> first character is equal to '#'; otherwise, <see langword="false"/>.</value>
bool IsComment { get; }

/// <summary>
/// Gets a value indicating whether this instance of IonReader is currently on table headers row.
/// </summary>
/// <value><c>true</c> if IonReader CurrentLine first character is equal to '|' and current table header was not already passed; otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if <see cref="IIonReader.CurrentLine"/> first character is equal to '|' and current table header was not already passed; otherwise, <see langword="false"/>.</value>
bool IsTableHeaderRow { get; }

/// <summary>
/// Gets a value indicating whether this instance of IonReader is currently on table row.
/// Gets a value indicating whether this instance of <see cref="IIonReader"/> is currently on table row.
/// </summary>
/// <value><c>true</c> if IonReader CurrentLine first character is equal to '|'; otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if <see cref="IIonReader.CurrentLine"/> first character is equal to '|'; otherwise, <see langword="false"/>.</value>
bool IsTableRow { get;}

/// <summary>
/// Gets a value indicating whether this instance of IonReader is currently on table header separator row. IMPORTANT: we recognize this
/// Gets a value indicating whether this instance of <see cref="IIonReader"/> is currently on table header separator row. IMPORTANT: we recognize this
/// property as a combination of first two characters as "|-". Fill your table rows without '-' character.
/// </summary>
/// <value><c>true</c> if IonReader CurrentLine first character is equal to '|-'; otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if <see cref="IIonReader.CurrentLine"/> first character is equal to '|-'; otherwise, <see langword="false"/>.</value>
bool IsTableHeaderSeparatorRow { get; }

/// <summary>
/// Gets a value indicating whether this instance of IonReader is currently on table row with data.
/// Gets a value indicating whether this instance of <see cref="IIonReader"/> is currently on table row with data.
/// </summary>
/// <value><c>true</c> if IonReader CurrentLine first character is equal to '|' and current table header was already passed; otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if <see cref="IIonReader.CurrentLine"/> first character is equal to '|' and current table header was already passed; otherwise, <see langword="false"/>.</value>
bool IsTableDataRow { get; }

/// <summary>
/// Gets a value indicating whether a IonReader CurrentLine is null, empty, or consists only of white-space characters.
/// Gets a value indicating whether a <see cref="IIonReader.CurrentLine"/> is <see langword="null"/>, empty, or consists only of white-space characters.
/// </summary>
/// <value><c>true</c> if string.IsNullOrWhiteSpace(CurrentLine); otherwise, <c>false</c>.</value>
/// <value><see langword="true"/> if string.IsNullOrWhiteSpace(CurrentLine); otherwise, <see langword="false"/>.</value>
bool IsEmptyLine { get; }

/// <summary>
Expand All @@ -69,7 +69,7 @@ public interface IIonReader : IDisposable
ArraySegment<char> CurrentRawLine { get; }

/// <summary>
/// Gets the name of current section. It is changing only when CurrentLine is on section header. Returns null only if Read() was not called yet.
/// Gets the name of current section. It is changing only when <see cref="IIonReader.CurrentLine"/> is on section header. Returns <see langword="null"/> only if <see cref="IIonReader.Read"/> was not called yet.
/// </summary>
/// <value>The current section.</value>
string? CurrentSection { get; }
Expand All @@ -83,7 +83,7 @@ public interface IIonReader : IDisposable
/// <summary>
/// Read this instance.
/// </summary>
/// <returns><c>true</c> if the next line was read successfully; otherwise,<c>false</c>.</returns>
/// <returns><see langword="true"/> if the next line was read successfully; otherwise,<see langword="false"/>.</returns>
bool Read();
}
}
Expand Down
16 changes: 8 additions & 8 deletions Anixe.Ion/IIonWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,46 +20,46 @@ public interface IIonWriter : IDisposable

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="value">Value to write</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
void WriteTableCell(int value, bool lastCellInRow = false);

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="value">Value to write. Cannot contain prohibited characters '\n' and '|'</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
/// <exception cref="Anixe.Ion.Exceptions.InvalidTableCellDataException">Value contains '\n' or '|' character</exception>>
void WriteTableCell(string? value, bool lastCellInRow = false);

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="value">Value to write. Cannot is one of prohibited characters '\n' and '|'</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
/// <exception cref="Anixe.Ion.Exceptions.InvalidTableCellDataException">Value is '\n' or '|' character</exception>>
void WriteTableCell(char value, bool lastCellInRow = false);

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="value">Value to write</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
void WriteTableCell(double value, bool lastCellInRow = false);

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="value">Value to write</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
void WriteTableCell(decimal value, bool lastCellInRow = false);

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="value">Value to write</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
void WriteTableCell(long value, bool lastCellInRow = false);

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="value">Value to write</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
void WriteTableCell(bool value, bool lastCellInRow = false);

/// <summary>Writes table cell value and adds table separators when needed.</summary>
/// <param name="buffer">The character array to write data from. Cannot contain prohibited characters '\n' and '|'</param>
/// <param name="index">The character position in the buffer at which to start retrieving data.</param>
/// <param name="count">The number of characters to write.</param>
/// <param name="lastCellInRow">Adds new line character when is set to true</param>
/// <param name="lastCellInRow">Adds new line character when is set to <see langword="true"/></param>
/// <exception cref="Anixe.Ion.Exceptions.InvalidTableCellDataException">Buffer contains '\n' or '|' character</exception>>
void WriteTableCell(char[] buffer, int index, int count, bool lastCellInRow = false);
void WriteEmptyLine();
Expand Down
19 changes: 19 additions & 0 deletions Anixe.Ion/IonExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace Anixe.Ion
{
public static class IonExtensions
{
/// <summary>
/// Creates ref-struct that represents key-value property.
/// </summary>
/// <param name="reader">Instance of <see cref="IIonReader"/> with current state <see cref="IIonReader.IsProperty"/>=<see langword="true"/>.</param>
/// <param name="propertySeparator">Character that separates key from value. By default it is used = character.</param>
/// <returns>An instance of <see cref="IonProperty"/> that has access to key and value spans in current line.</returns>
/// <exception cref="InvalidOperationException">Reader is in not correct state. That means <see cref="IIonReader.IsProperty"/> is <see langword="false"/>.</exception>
public static IonProperty ReadProperty(this IIonReader reader, char propertySeparator = '=')
{
return new IonProperty(reader, propertySeparator);
}
}
}
39 changes: 39 additions & 0 deletions Anixe.Ion/IonProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;

namespace Anixe.Ion
{
/// <summary>
/// Represents a ref-struct that accesses key and value of property of <see cref="IIonReader"/>.
/// </summary>
public ref struct IonProperty
{
public readonly ReadOnlySpan<char> Key;
public readonly ReadOnlySpan<char> Value;

/// <summary>
/// Creates a new instance of <see cref="IonProperty"/>.
/// </summary>
/// <param name="reader">Instance of <see cref="IIonReader"/> with current state <see cref="IIonReader.IsProperty"/>=<see langword="true"/>.</param>
/// <param name="propertySeparator">Character that separates key from value. By default it is used = character.</param>
/// <exception cref="InvalidOperationException">Reader is in not correct state. That means <see cref="IIonReader.IsProperty"/> is <see langword="false"/>.</exception>
public IonProperty(IIonReader reader, char propertySeparator = '=')
{
if (!reader.IsProperty)
{
throw new InvalidOperationException("Cannot read property when reader in not on property line.");
}

var span = (ReadOnlySpan<char>)reader.CurrentRawLine.AsSpan();
var sepIdx = span.IndexOf(propertySeparator);
if (sepIdx == -1)
{
this.Key = ReadOnlySpan<char>.Empty;
this.Value = span;
return;
}

this.Key = span.Slice(0, sepIdx).Trim().Trim('"');
this.Value = span.Slice(sepIdx + 1, span.Length - sepIdx - 1).Trim().Trim('"');
}
}
}
Loading

0 comments on commit 806cdbf

Please sign in to comment.