From 91c0966ceff7cebfa59abc68865027281d3cf5eb Mon Sep 17 00:00:00 2001 From: sveinungf Date: Wed, 27 Dec 2023 23:24:28 +0100 Subject: [PATCH] Get cell value writers from indexing into a static array --- .../CellValueWriters/CellValueWriter.cs | 25 +++++++++----- .../CellValueWriters/CellWriterType.cs | 14 ++++++++ SpreadCheetah/CellWriters/BaseCellWriter.cs | 7 ++-- .../CellWriters/CellWithReferenceWriter.cs | 9 ++--- SpreadCheetah/CellWriters/CellWriter.cs | 34 ++++++++++++------- .../DataCellWithReferenceWriter.cs | 7 ++-- SpreadCheetah/CellWriters/DataCellWriter.cs | 7 ++-- .../StyledCellWithReferenceWriter.cs | 14 +++++--- SpreadCheetah/CellWriters/StyledCellWriter.cs | 11 +++--- SpreadCheetah/DataCell.cs | 30 +++++++--------- 10 files changed, 98 insertions(+), 60 deletions(-) create mode 100644 SpreadCheetah/CellValueWriters/CellWriterType.cs diff --git a/SpreadCheetah/CellValueWriters/CellValueWriter.cs b/SpreadCheetah/CellValueWriters/CellValueWriter.cs index fb367de9..c65a7de6 100644 --- a/SpreadCheetah/CellValueWriters/CellValueWriter.cs +++ b/SpreadCheetah/CellValueWriters/CellValueWriter.cs @@ -4,20 +4,27 @@ using SpreadCheetah.CellWriters; using SpreadCheetah.Styling; using SpreadCheetah.Styling.Internal; +using System.Runtime.CompilerServices; namespace SpreadCheetah.CellValueWriters; internal abstract class CellValueWriter { - public static CellValueWriter Null { get; } = new NullValueWriter(); - public static CellValueWriter Integer { get; } = new IntegerCellValueWriter(); - public static CellValueWriter Float { get; } = new FloatCellValueWriter(); - public static CellValueWriter Double { get; } = new DoubleCellValueWriter(); - public static CellValueWriter DateTime { get; } = new DateTimeCellValueWriter(); - public static CellValueWriter NullDateTime { get; } = new NullDateTimeCellValueWriter(); - public static CellValueWriter TrueBoolean { get; } = new TrueBooleanCellValueWriter(); - public static CellValueWriter FalseBoolean { get; } = new FalseBooleanCellValueWriter(); - public static CellValueWriter String { get; } = new StringCellValueWriter(); + private static readonly CellValueWriter[] Writers = + [ + new NullValueWriter(), + new IntegerCellValueWriter(), + new FloatCellValueWriter(), + new DoubleCellValueWriter(), + new DateTimeCellValueWriter(), + new NullDateTimeCellValueWriter(), + new TrueBooleanCellValueWriter(), + new FalseBooleanCellValueWriter(), + new StringCellValueWriter() + ]; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static CellValueWriter GetWriter(CellWriterType type) => Writers[(int)type]; public abstract bool TryWriteCell(in DataCell cell, DefaultStyling? defaultStyling, SpreadsheetBuffer buffer); public abstract bool TryWriteCell(in DataCell cell, StyleId styleId, SpreadsheetBuffer buffer); diff --git a/SpreadCheetah/CellValueWriters/CellWriterType.cs b/SpreadCheetah/CellValueWriters/CellWriterType.cs new file mode 100644 index 00000000..cdcc394f --- /dev/null +++ b/SpreadCheetah/CellValueWriters/CellWriterType.cs @@ -0,0 +1,14 @@ +namespace SpreadCheetah.CellValueWriters; + +internal enum CellWriterType : byte +{ + Null, + Integer, + Float, + Double, + DateTime, + NullDateTime, + TrueBoolean, + FalseBoolean, + String +} \ No newline at end of file diff --git a/SpreadCheetah/CellWriters/BaseCellWriter.cs b/SpreadCheetah/CellWriters/BaseCellWriter.cs index 7d128e57..1865d547 100644 --- a/SpreadCheetah/CellWriters/BaseCellWriter.cs +++ b/SpreadCheetah/CellWriters/BaseCellWriter.cs @@ -1,3 +1,4 @@ +using SpreadCheetah.CellValueWriters; using SpreadCheetah.Helpers; using SpreadCheetah.Styling.Internal; using SpreadCheetah.Worksheets; @@ -259,13 +260,15 @@ private async ValueTask WriteCellPieceByPieceAsync(T cell, Stream stream, Cancel protected bool FinishWritingFormulaCellValue(in Cell cell, string formulaText, ref int cellValueIndex) { + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); + // Write the formula if (cellValueIndex < formulaText.Length) { if (!Buffer.WriteLongString(formulaText, ref cellValueIndex)) return false; // Finish if there is no cached value to write piece by piece - if (!cell.DataCell.Writer.CanWriteValuePieceByPiece(cell.DataCell)) return true; + if (!writer.CanWriteValuePieceByPiece(cell.DataCell)) return true; } // If there is a cached value, we need to write "[FORMULA][CACHEDVALUE]" @@ -282,7 +285,7 @@ protected bool FinishWritingFormulaCellValue(in Cell cell, string formulaText, r // Write the cached value var cachedValueIndex = cellValueIndex - cachedValueStartIndex; - var result = cell.DataCell.Writer.WriteValuePieceByPiece(cell.DataCell, Buffer, ref cachedValueIndex); + var result = writer.WriteValuePieceByPiece(cell.DataCell, Buffer, ref cachedValueIndex); cellValueIndex = cachedValueIndex + cachedValueStartIndex; return result; } diff --git a/SpreadCheetah/CellWriters/CellWithReferenceWriter.cs b/SpreadCheetah/CellWriters/CellWithReferenceWriter.cs index be3d0204..73f3eb20 100644 --- a/SpreadCheetah/CellWriters/CellWithReferenceWriter.cs +++ b/SpreadCheetah/CellWriters/CellWithReferenceWriter.cs @@ -1,3 +1,4 @@ +using SpreadCheetah.CellValueWriters; using SpreadCheetah.Styling.Internal; namespace SpreadCheetah.CellWriters; @@ -7,7 +8,7 @@ internal sealed class CellWithReferenceWriter(CellWriterState state, DefaultStyl { protected override bool TryWriteCell(in Cell cell) { - var writer = cell.DataCell.Writer; + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); return cell switch { { Formula: { } f } => writer.TryWriteCellWithReference(f.FormulaText, cell.DataCell, cell.StyleId, DefaultStyling, State), @@ -18,7 +19,7 @@ protected override bool TryWriteCell(in Cell cell) protected override bool WriteStartElement(in Cell cell) { - var writer = cell.DataCell.Writer; + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); return cell switch { { Formula: not null } => writer.WriteFormulaStartElementWithReference(cell.StyleId, DefaultStyling, State), @@ -29,13 +30,13 @@ protected override bool WriteStartElement(in Cell cell) protected override bool TryWriteEndElement(in Cell cell) { - return cell.DataCell.Writer.TryWriteEndElement(cell, Buffer); + return CellValueWriter.GetWriter(cell.DataCell.Type).TryWriteEndElement(cell, Buffer); } protected override bool FinishWritingCellValue(in Cell cell, ref int cellValueIndex) { return cell.Formula is { } formula ? FinishWritingFormulaCellValue(cell, formula.FormulaText, ref cellValueIndex) - : cell.DataCell.Writer.WriteValuePieceByPiece(cell.DataCell, Buffer, ref cellValueIndex); + : CellValueWriter.GetWriter(cell.DataCell.Type).WriteValuePieceByPiece(cell.DataCell, Buffer, ref cellValueIndex); } } diff --git a/SpreadCheetah/CellWriters/CellWriter.cs b/SpreadCheetah/CellWriters/CellWriter.cs index edcc8ad0..974ac8bd 100644 --- a/SpreadCheetah/CellWriters/CellWriter.cs +++ b/SpreadCheetah/CellWriters/CellWriter.cs @@ -1,3 +1,4 @@ +using SpreadCheetah.CellValueWriters; using SpreadCheetah.Styling.Internal; namespace SpreadCheetah.CellWriters; @@ -5,29 +6,38 @@ namespace SpreadCheetah.CellWriters; internal sealed class CellWriter(CellWriterState state, DefaultStyling? defaultStyling) : BaseCellWriter(state, defaultStyling) { - protected override bool TryWriteCell(in Cell cell) => cell switch + protected override bool TryWriteCell(in Cell cell) { - { Formula: { } formula } => cell.DataCell.Writer.TryWriteCell(formula.FormulaText, cell.DataCell, cell.StyleId, DefaultStyling, Buffer), - { StyleId: not null } => cell.DataCell.Writer.TryWriteCell(cell.DataCell, cell.StyleId, Buffer), - _ => cell.DataCell.Writer.TryWriteCell(cell.DataCell, DefaultStyling, Buffer) - }; + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); + return cell switch + { + { Formula: { } formula } => writer.TryWriteCell(formula.FormulaText, cell.DataCell, cell.StyleId, DefaultStyling, Buffer), + { StyleId: not null } => writer.TryWriteCell(cell.DataCell, cell.StyleId, Buffer), + _ => writer.TryWriteCell(cell.DataCell, DefaultStyling, Buffer) + }; + } - protected override bool WriteStartElement(in Cell cell) => cell switch + protected override bool WriteStartElement(in Cell cell) { - { Formula: not null } => cell.DataCell.Writer.WriteFormulaStartElement(cell.StyleId, DefaultStyling, Buffer), - { StyleId: not null } => cell.DataCell.Writer.WriteStartElement(cell.StyleId, Buffer), - _ => cell.DataCell.Writer.WriteStartElement(Buffer) - }; + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); + return cell switch + { + { Formula: not null } => writer.WriteFormulaStartElement(cell.StyleId, DefaultStyling, Buffer), + { StyleId: not null } => writer.WriteStartElement(cell.StyleId, Buffer), + _ => writer.WriteStartElement(Buffer) + }; + } protected override bool TryWriteEndElement(in Cell cell) { - return cell.DataCell.Writer.TryWriteEndElement(cell, Buffer); + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); + return writer.TryWriteEndElement(cell, Buffer); } protected override bool FinishWritingCellValue(in Cell cell, ref int cellValueIndex) { return cell.Formula is { } formula ? FinishWritingFormulaCellValue(cell, formula.FormulaText, ref cellValueIndex) - : cell.DataCell.Writer.WriteValuePieceByPiece(cell.DataCell, Buffer, ref cellValueIndex); + : CellValueWriter.GetWriter(cell.DataCell.Type).WriteValuePieceByPiece(cell.DataCell, Buffer, ref cellValueIndex); } } diff --git a/SpreadCheetah/CellWriters/DataCellWithReferenceWriter.cs b/SpreadCheetah/CellWriters/DataCellWithReferenceWriter.cs index 3cdb96ad..a57235e0 100644 --- a/SpreadCheetah/CellWriters/DataCellWithReferenceWriter.cs +++ b/SpreadCheetah/CellWriters/DataCellWithReferenceWriter.cs @@ -1,3 +1,4 @@ +using SpreadCheetah.CellValueWriters; using SpreadCheetah.Styling.Internal; namespace SpreadCheetah.CellWriters; @@ -7,17 +8,17 @@ internal sealed class DataCellWithReferenceWriter(CellWriterState state, Default { protected override bool TryWriteCell(in DataCell cell) { - return cell.Writer.TryWriteCellWithReference(cell, DefaultStyling, State); + return CellValueWriter.GetWriter(cell.Type).TryWriteCellWithReference(cell, DefaultStyling, State); } protected override bool WriteStartElement(in DataCell cell) { - return cell.Writer.WriteStartElementWithReference(State); + return CellValueWriter.GetWriter(cell.Type).WriteStartElementWithReference(State); } protected override bool TryWriteEndElement(in DataCell cell) { - return cell.Writer.TryWriteEndElement(Buffer); + return CellValueWriter.GetWriter(cell.Type).TryWriteEndElement(Buffer); } protected override bool FinishWritingCellValue(in DataCell cell, ref int cellValueIndex) diff --git a/SpreadCheetah/CellWriters/DataCellWriter.cs b/SpreadCheetah/CellWriters/DataCellWriter.cs index a8ad5a74..76d5810f 100644 --- a/SpreadCheetah/CellWriters/DataCellWriter.cs +++ b/SpreadCheetah/CellWriters/DataCellWriter.cs @@ -1,3 +1,4 @@ +using SpreadCheetah.CellValueWriters; using SpreadCheetah.Styling.Internal; namespace SpreadCheetah.CellWriters; @@ -7,17 +8,17 @@ internal sealed class DataCellWriter(CellWriterState state, DefaultStyling? defa { protected override bool TryWriteCell(in DataCell cell) { - return cell.Writer.TryWriteCell(cell, DefaultStyling, Buffer); + return CellValueWriter.GetWriter(cell.Type).TryWriteCell(cell, DefaultStyling, Buffer); } protected override bool WriteStartElement(in DataCell cell) { - return cell.Writer.WriteStartElement(Buffer); + return CellValueWriter.GetWriter(cell.Type).WriteStartElement(Buffer); } protected override bool TryWriteEndElement(in DataCell cell) { - return cell.Writer.TryWriteEndElement(Buffer); + return CellValueWriter.GetWriter(cell.Type).TryWriteEndElement(Buffer); } protected override bool FinishWritingCellValue(in DataCell cell, ref int cellValueIndex) diff --git a/SpreadCheetah/CellWriters/StyledCellWithReferenceWriter.cs b/SpreadCheetah/CellWriters/StyledCellWithReferenceWriter.cs index 4a1fe680..6b69343f 100644 --- a/SpreadCheetah/CellWriters/StyledCellWithReferenceWriter.cs +++ b/SpreadCheetah/CellWriters/StyledCellWithReferenceWriter.cs @@ -1,3 +1,4 @@ +using SpreadCheetah.CellValueWriters; using SpreadCheetah.Styling.Internal; namespace SpreadCheetah.CellWriters; @@ -7,21 +8,24 @@ internal sealed class StyledCellWithReferenceWriter(CellWriterState state, Defau { protected override bool TryWriteCell(in StyledCell cell) { + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); return cell.StyleId is null - ? cell.DataCell.Writer.TryWriteCellWithReference(cell.DataCell, DefaultStyling, State) - : cell.DataCell.Writer.TryWriteCellWithReference(cell.DataCell, cell.StyleId, State); + ? writer.TryWriteCellWithReference(cell.DataCell, DefaultStyling, State) + : writer.TryWriteCellWithReference(cell.DataCell, cell.StyleId, State); } protected override bool WriteStartElement(in StyledCell cell) { + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); return cell.StyleId is null - ? cell.DataCell.Writer.WriteStartElementWithReference(State) - : cell.DataCell.Writer.WriteStartElementWithReference(cell.StyleId, State); + ? writer.WriteStartElementWithReference(State) + : writer.WriteStartElementWithReference(cell.StyleId, State); } protected override bool TryWriteEndElement(in StyledCell cell) { - return cell.DataCell.Writer.TryWriteEndElement(Buffer); + var writer = CellValueWriter.GetWriter(cell.DataCell.Type); + return writer.TryWriteEndElement(Buffer); } protected override bool FinishWritingCellValue(in StyledCell cell, ref int cellValueIndex) diff --git a/SpreadCheetah/CellWriters/StyledCellWriter.cs b/SpreadCheetah/CellWriters/StyledCellWriter.cs index c24be224..baf51a01 100644 --- a/SpreadCheetah/CellWriters/StyledCellWriter.cs +++ b/SpreadCheetah/CellWriters/StyledCellWriter.cs @@ -1,3 +1,4 @@ +using SpreadCheetah.CellValueWriters; using SpreadCheetah.Styling.Internal; namespace SpreadCheetah.CellWriters; @@ -8,20 +9,20 @@ internal sealed class StyledCellWriter(CellWriterState state, DefaultStyling? de protected override bool TryWriteCell(in StyledCell cell) { return cell.StyleId is null - ? cell.DataCell.Writer.TryWriteCell(cell.DataCell, DefaultStyling, Buffer) - : cell.DataCell.Writer.TryWriteCell(cell.DataCell, cell.StyleId, Buffer); + ? CellValueWriter.GetWriter(cell.DataCell.Type).TryWriteCell(cell.DataCell, DefaultStyling, Buffer) + : CellValueWriter.GetWriter(cell.DataCell.Type).TryWriteCell(cell.DataCell, cell.StyleId, Buffer); } protected override bool WriteStartElement(in StyledCell cell) { return cell.StyleId is null - ? cell.DataCell.Writer.WriteStartElement(Buffer) - : cell.DataCell.Writer.WriteStartElement(cell.StyleId, Buffer); + ? CellValueWriter.GetWriter(cell.DataCell.Type).WriteStartElement(Buffer) + : CellValueWriter.GetWriter(cell.DataCell.Type).WriteStartElement(cell.StyleId, Buffer); } protected override bool TryWriteEndElement(in StyledCell cell) { - return cell.DataCell.Writer.TryWriteEndElement(Buffer); + return CellValueWriter.GetWriter(cell.DataCell.Type).TryWriteEndElement(Buffer); } protected override bool FinishWritingCellValue(in StyledCell cell, ref int cellValueIndex) diff --git a/SpreadCheetah/DataCell.cs b/SpreadCheetah/DataCell.cs index 12d4fee6..81c61079 100644 --- a/SpreadCheetah/DataCell.cs +++ b/SpreadCheetah/DataCell.cs @@ -8,13 +8,9 @@ namespace SpreadCheetah; /// public readonly record struct DataCell { - private readonly CellValueWriter? _writer; - internal CellValue NumberValue { get; } - internal string? StringValue { get; } - - internal CellValueWriter Writer => _writer ?? CellValueWriter.Null; + internal CellWriterType Type { get; } /// /// Initializes a new instance of the struct with a text value. @@ -23,7 +19,7 @@ public readonly record struct DataCell public DataCell(string? value) { StringValue = value != null ? WebUtility.HtmlEncode(value) : string.Empty; - _writer = value != null ? CellValueWriter.String : CellValueWriter.Null; + Type = value != null ? CellWriterType.String : CellWriterType.Null; } /// @@ -32,7 +28,7 @@ public DataCell(string? value) public DataCell(int value) { NumberValue = new CellValue(value); - _writer = CellValueWriter.Integer; + Type = CellWriterType.Integer; } /// @@ -42,7 +38,7 @@ public DataCell(int value) public DataCell(int? value) { NumberValue = value is null ? new CellValue() : new CellValue(value.GetValueOrDefault()); - _writer = value is null ? CellValueWriter.Null : CellValueWriter.Integer; + Type = value is null ? CellWriterType.Null : CellWriterType.Integer; } /// @@ -68,7 +64,7 @@ public DataCell(long? value) : this((double?)value) public DataCell(float value) { NumberValue = new CellValue(value); - _writer = CellValueWriter.Float; + Type = CellWriterType.Float; } /// @@ -78,7 +74,7 @@ public DataCell(float value) public DataCell(float? value) { NumberValue = value is null ? new CellValue() : new CellValue(value.GetValueOrDefault()); - _writer = value is null ? CellValueWriter.Null : CellValueWriter.Float; + Type = value is null ? CellWriterType.Null : CellWriterType.Float; } /// @@ -88,7 +84,7 @@ public DataCell(float? value) public DataCell(double value) { NumberValue = new CellValue(value); - _writer = CellValueWriter.Double; + Type = CellWriterType.Double; } /// @@ -99,7 +95,7 @@ public DataCell(double value) public DataCell(double? value) { NumberValue = value is null ? new CellValue() : new CellValue(value.GetValueOrDefault()); - _writer = value is null ? CellValueWriter.Null : CellValueWriter.Double; + Type = value is null ? CellWriterType.Null : CellWriterType.Double; } /// @@ -126,7 +122,7 @@ public DataCell(decimal? value) : this(value != null ? decimal.ToDouble(value.Ge public DataCell(DateTime value) { NumberValue = new CellValue(value.ToOADate()); - _writer = CellValueWriter.DateTime; + Type = CellWriterType.DateTime; } /// @@ -137,7 +133,7 @@ public DataCell(DateTime value) public DataCell(DateTime? value) { NumberValue = value is null ? new CellValue() : new CellValue(value.GetValueOrDefault().ToOADate()); - _writer = value is null ? CellValueWriter.NullDateTime : CellValueWriter.DateTime; + Type = value is null ? CellWriterType.NullDateTime : CellWriterType.DateTime; } /// @@ -145,7 +141,7 @@ public DataCell(DateTime? value) /// public DataCell(bool value) { - _writer = GetBooleanWriter(value); + Type = GetBooleanWriter(value); } /// @@ -154,8 +150,8 @@ public DataCell(bool value) /// public DataCell(bool? value) { - _writer = value is null ? CellValueWriter.Null : GetBooleanWriter(value.GetValueOrDefault()); + Type = value is null ? CellWriterType.Null : GetBooleanWriter(value.GetValueOrDefault()); } - private static CellValueWriter GetBooleanWriter(bool value) => value ? CellValueWriter.TrueBoolean : CellValueWriter.FalseBoolean; + private static CellWriterType GetBooleanWriter(bool value) => value ? CellWriterType.TrueBoolean : CellWriterType.FalseBoolean; }