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

Minor optimizations #61

Merged
merged 9 commits into from
Jun 30, 2024
7 changes: 4 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
</PropertyGroup>
<ItemGroup>
<GlobalPackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.4.0-beta.1" />
<GlobalPackageReference Include="Meziantou.Analyzer" Version="2.0.158" />
<GlobalPackageReference Include="Meziantou.Analyzer" Version="2.0.159" />
<GlobalPackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
<GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.10.48" />
<GlobalPackageReference Include="PrimaryConstructorAnalyzer" Version="1.0.6" />
<GlobalPackageReference Include="Roslynator.Analyzers" Version="4.12.4" />
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.27.0.93347" />
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.28.0.94264" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
Expand All @@ -33,7 +34,7 @@
<PackageVersion Include="System.Memory" Version="4.5.5" />
<PackageVersion Include="TngTech.ArchUnitNET.xUnit" Version="0.10.6" />
<PackageVersion Include="Verify.SourceGenerators" Version="2.2.0" />
<PackageVersion Include="Verify.Xunit" Version="25.0.3" />
<PackageVersion Include="Verify.Xunit" Version="25.0.4" />
<PackageVersion Include="xunit" Version="2.8.1" />
<PackageVersion Include="xunit.assert" Version="2.8.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.1" />
Expand Down
43 changes: 17 additions & 26 deletions SpreadCheetah/CellWriters/BaseCellWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,50 +68,41 @@

private bool TryAddRowCells(IList<T> cells)
{
return TryGetSpan(cells, out var span)
? TryAddRowCellsForSpan(span)
: TryAddRowCellsForList(cells);
}

private static bool TryGetSpan(IList<T> cells, out ReadOnlySpan<T> span)
{
if (cells is T[] cellArray)
return cells switch
{
span = cellArray.AsSpan();
return true;
}

T[] cellArray => TryAddRowCellsForSpan(cellArray),

Check warning on line 73 in SpreadCheetah/CellWriters/BaseCellWriter.cs

View check run for this annotation

Codecov / codecov/patch

SpreadCheetah/CellWriters/BaseCellWriter.cs#L73

Added line #L73 was not covered by tests
#if NET5_0_OR_GREATER
if (cells is List<T> cellList)
{
span = System.Runtime.InteropServices.CollectionsMarshal.AsSpan(cellList);
return true;
}
List<T> cellList => TryAddRowCellsForSpan(System.Runtime.InteropServices.CollectionsMarshal.AsSpan(cellList)),
#endif

span = [];
return false;
_ => TryAddRowCellsForList(cells)
};
}

private bool TryAddRowCellsForSpan(ReadOnlySpan<T> cells)
{
for (; State.Column < cells.Length; ++State.Column)
var writerState = State;
var column = writerState.Column;
while (column < cells.Length)
{
// Write cell if it fits in the buffer
if (!TryWriteCell(cells[State.Column]))
if (!TryWriteCell(cells[column]))
return false;

writerState.Column = ++column;
}

return TryWriteRowEnd();
}

private bool TryAddRowCellsForList(IList<T> cells)
{
for (; State.Column < cells.Count; ++State.Column)
var writerState = State;
var column = writerState.Column;
while (column < cells.Count)
{
// Write cell if it fits in the buffer
if (!TryWriteCell(cells[State.Column]))
if (!TryWriteCell(cells[column]))
return false;

writerState.Column = ++column;
}

return TryWriteRowEnd();
Expand Down
35 changes: 4 additions & 31 deletions SpreadCheetah/Helpers/CellRowHelper.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,19 @@
using SpreadCheetah.Worksheets;
using System.Buffers.Text;

namespace SpreadCheetah.Helpers;

internal static class CellRowHelper
{
public static bool TryWriteRowStart(uint rowIndex, SpreadsheetBuffer buffer)
{
var bytes = buffer.GetSpan();

if (RowStart.TryCopyTo(bytes)
&& Utf8Formatter.TryFormat(rowIndex, bytes.Slice(RowStart.Length), out var part2)
&& RowStartEndTag.TryCopyTo(bytes.Slice(RowStart.Length + part2)))
{
buffer.Advance(RowStart.Length + RowStartEndTag.Length + part2);
return true;
}

return false;
return buffer.TryWrite($"{RowStart}{rowIndex}{RowStartEndTag}");
}

public static bool TryWriteRowStart(uint rowIndex, RowOptions options, SpreadsheetBuffer buffer)
{
if (options.Height is not { } height)
return TryWriteRowStart(rowIndex, buffer);

var bytes = buffer.GetSpan();
var part1 = RowStart.Length;
var part3 = RowHeightStart.Length;
var part5 = RowHeightEnd.Length;

if (RowStart.TryCopyTo(bytes)
&& Utf8Formatter.TryFormat(rowIndex, bytes.Slice(part1), out var part2)
&& RowHeightStart.TryCopyTo(bytes.Slice(part1 + part2))
&& Utf8Formatter.TryFormat(height, bytes.Slice(part1 + part2 + part3), out var part4)
&& RowHeightEnd.TryCopyTo(bytes.Slice(part1 + part2 + part3 + part4)))
{
buffer.Advance(part1 + part2 + part3 + part4 + part5);
return true;
}

return false;
return options.Height is { } height
? buffer.TryWrite($"{RowStart}{rowIndex}{RowHeightStart}{height}{RowHeightEnd}")
: TryWriteRowStart(rowIndex, buffer);
}

private static ReadOnlySpan<byte> RowStart => "<row r=\""u8;
Expand Down
35 changes: 20 additions & 15 deletions SpreadCheetah/SpreadsheetBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

public void Dispose() => ArrayPool<byte>.Shared.Return(_buffer, true);
public Span<byte> GetSpan() => _buffer.AsSpan(_index);
private Span<byte> GetSpan(int start) => _buffer.AsSpan(_index + start);
public void Advance(int bytes) => _index += bytes;

public bool WriteLongString(ReadOnlySpan<char> value, ref int valueIndex)
Expand Down Expand Up @@ -54,31 +55,24 @@

public bool TryWrite([InterpolatedStringHandlerArgument("")] ref TryWriteInterpolatedStringHandler handler)
{
if (handler._success)
var pos = handler._pos;
if (pos != 0)
{
Advance(handler._pos);
Advance(pos);
return true;
}

return false;
}

[InterpolatedStringHandler]
public ref struct TryWriteInterpolatedStringHandler
#pragma warning disable CS9113 // Parameter is unread.
public ref struct TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, SpreadsheetBuffer buffer)
#pragma warning restore CS9113 // Parameter is unread.
{
private readonly SpreadsheetBuffer _buffer;
internal int _pos;
internal bool _success;

public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, SpreadsheetBuffer buffer)
{
_ = literalLength;
_ = formattedCount;
_buffer = buffer;
_success = true;
}

private readonly Span<byte> GetSpan() => _buffer._buffer.AsSpan(_buffer._index + _pos);
private readonly Span<byte> GetSpan() => buffer.GetSpan(_pos);

[ExcludeFromCodeCoverage]
public bool AppendLiteral(string value)
Expand All @@ -105,6 +99,17 @@
return Fail();
}

public bool AppendFormatted(uint value)
{
if (Utf8Formatter.TryFormat(value, GetSpan(), out var bytesWritten))
{
_pos += bytesWritten;
return true;
}

return Fail();

Check warning on line 110 in SpreadCheetah/SpreadsheetBuffer.cs

View check run for this annotation

Codecov / codecov/patch

SpreadCheetah/SpreadsheetBuffer.cs#L110

Added line #L110 was not covered by tests
}

public bool AppendFormatted(float value)
{
if (Utf8Formatter.TryFormat(value, GetSpan(), out var bytesWritten))
Expand Down Expand Up @@ -180,7 +185,7 @@

private bool Fail()
{
_success = false;
_pos = 0;
return false;
}
}
Expand Down
Loading