Skip to content

Commit

Permalink
SepReader.Cols: Add JoinPathsToString (net9.0+ only due to Path.Join(…
Browse files Browse the repository at this point in the history
…Span<>) only) (#254)
  • Loading branch information
nietras authored Jan 31, 2025
1 parent 8429e4f commit 6b7aa58
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2070,6 +2070,7 @@ namespace nietras.SeparatedValues
public nietras.SeparatedValues.SepReader.Col this[int index] { get; }
public string CombinePathsToString() { }
public System.ReadOnlySpan<char> Join(System.ReadOnlySpan<char> separator) { }
public string JoinPathsToString() { }
public string JoinToString(System.ReadOnlySpan<char> separator) { }
public System.Span<T> Parse<T>()
where T : System.ISpanParsable<T> { }
Expand Down
25 changes: 17 additions & 8 deletions src/Sep.Test/SepReaderColsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ namespace nietras.SeparatedValues.Test;
[TestClass]
public class SepReaderColsTest
{
const int _colsCount = 3;
static readonly string[] _colNames = ["A", "B", "C"];
const int _colsCount = 5;
static readonly string[] _colNames = ["A", "B", "C", "D", "E"];
static readonly int[] _colIndices = Enumerable.Range(0, _colsCount).ToArray();
static readonly int[] _colValues = [10, 11, 12];
static readonly int[] _colValues = [10, 11, 12, 13, 14];
static readonly float[] _colValuesFloat = _colValues.Select(i => (float)i).ToArray();
static readonly string[] _colTexts = _colValues.Select(i => i.ToString()).ToArray();
const string Text = """
A;B;C
10;11;12
A;B;C;D;E
10;11;12;13;14
""";
static readonly int?[] _colValuesUnparseable = [null, null, 12];
static readonly int?[] _colValuesUnparseable = [null, null, 12, null, 14];
const string TextUnparseable = """
A;B;C
1a;;12
A;B;C;D;E
1a;;12;;14
""";

[TestMethod]
Expand Down Expand Up @@ -194,6 +194,12 @@ public void SepReaderColsTest_Join(string separator)
}

#if NET9_0_OR_GREATER
[TestMethod]
public void SepReaderColsTest_JoinPathsToString()
{
Run((cols, range) => Assert.AreEqual(Path.Join(_colTexts[range]), cols.JoinPathsToString()));
}

[TestMethod]
public void SepReaderColsTest_CombinePathsToString()
{
Expand All @@ -211,9 +217,12 @@ static void Run(ColsTestAction action, string text = Text, bool checkIndexOutOfR
0..0,
0..1,
0..2,
0..3,
0..4,
0.._colsCount,
1..1,
1..2,
1..3,
1.._colsCount,
2..2,
2.._colsCount,
Expand Down
4 changes: 4 additions & 0 deletions src/Sep/SepReader.Cols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ public string JoinToString(ReadOnlySpan<char> separator) => IsIndices()
: _state.JoinToString(_colStartIfRange, _colIndices.Length, separator);

#if NET9_0_OR_GREATER
public string JoinPathsToString() => IsIndices()
? _state.JoinPathsToString(_colIndices)
: _state.JoinPathsToString(_colStartIfRange, _colIndices.Length);

public string CombinePathsToString() => IsIndices()
? _state.CombinePathsToString(_colIndices)
: _state.CombinePathsToString(_colStartIfRange, _colIndices.Length);
Expand Down
64 changes: 62 additions & 2 deletions src/Sep/SepReaderState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -709,10 +709,31 @@ internal string JoinToString(ReadOnlySpan<int> colIndices, scoped ReadOnlySpan<c

#if NET9_0_OR_GREATER
[SkipLocalsInit]
internal string JoinPathsToString(ReadOnlySpan<int> colIndices)
{
var length = colIndices.Length;
if (length == 0) { return string.Empty; }
if (length == 1) { return ToStringDefault(colIndices[0]); }
if (length <= 4)
{
Span<SepRange> colRanges = stackalloc SepRange[colIndices.Length];
GetColRanges(colIndices, colRanges);
return JoinPathsToString(colRanges);
}
else
{
var paths = ToStrings(colIndices);
#pragma warning disable CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.
return Path.Join(paths);
#pragma warning restore CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.
}
}

internal string CombinePathsToString(ReadOnlySpan<int> colIndices)
{
if (colIndices.Length == 0) { return string.Empty; }
if (colIndices.Length == 1) { return ToStringDefault(colIndices[0]); }
var length = colIndices.Length;
if (length == 0) { return string.Empty; }
if (length == 1) { return ToStringDefault(colIndices[0]); }
var paths = ToStrings(colIndices);
return Path.Combine(paths);
}
Expand Down Expand Up @@ -838,8 +859,27 @@ internal string JoinToString(int colStart, int colCount, scoped ReadOnlySpan<cha
return JoinToString(colRanges, separator);
}


#if NET9_0_OR_GREATER
[SkipLocalsInit]
internal string JoinPathsToString(int colStart, int colCount)
{
if (colCount == 0) { return string.Empty; }
if (colCount == 1) { return ToStringDefault(colStart); }
if (colCount <= 4)
{
Span<SepRange> colRanges = stackalloc SepRange[colCount];
GetColRanges(colStart, colRanges);
return JoinPathsToString(colRanges);
}
else
{
var paths = ToStrings(colStart, colCount);
#pragma warning disable CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.
return Path.Join(paths);
#pragma warning restore CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.
}
}
internal string CombinePathsToString(int colStart, int colCount)
{
if (colCount == 0) { return string.Empty; }
Expand Down Expand Up @@ -892,6 +932,26 @@ string JoinToString(scoped ReadOnlySpan<SepRange> colRanges, scoped ReadOnlySpan
#endif
}

#if NET9_0_OR_GREATER
string JoinPathsToString(scoped ReadOnlySpan<SepRange> colRanges)
{
var length = colRanges.Length;
A.Assert(1 < length && length <= 4);

var chars = _chars.AsSpan();
var colSpan0 = GetSpan(chars, colRanges[0]);
var colSpan1 = GetSpan(chars, colRanges[1]);
if (length == 2) { return Path.Join(colSpan0, colSpan1); }
var colSpan2 = GetSpan(chars, colRanges[2]);
if (length == 3) { return Path.Join(colSpan0, colSpan1, colSpan2); }
var colSpan3 = GetSpan(chars, colRanges[3]);
return Path.Join(colSpan0, colSpan1, colSpan2, colSpan3);

static ReadOnlySpan<char> GetSpan(ReadOnlySpan<char> chars, SepRange range) =>
chars.Slice(range.Start, range.Length);
}
#endif

static void Join(ReadOnlySpan<char> chars,
ReadOnlySpan<SepRange> colRanges, ReadOnlySpan<char> separator,
Span<char> join)
Expand Down

0 comments on commit 6b7aa58

Please sign in to comment.