From 05292efc8a6f6107837c53e482f604753de9ac56 Mon Sep 17 00:00:00 2001 From: Josh Close Date: Tue, 20 Feb 2018 22:44:59 -0600 Subject: [PATCH] Reading performance improvements. --- .../CsvHelper.Performance.csproj | 2 +- src/CsvHelper.Performance/Program.cs | 31 ++- .../Configuration/ClassMapBuilderTests.cs | 2 +- src/CsvHelper.Tests/Mocks/ParserMock.cs | 2 +- src/CsvHelper.Tests/Mocks/SerializerMock.cs | 2 +- src/CsvHelper.sln | 13 +- src/CsvHelper/BadDataException.cs | 6 +- src/CsvHelper/Configuration/Configuration.cs | 6 +- .../Configuration/IParserConfiguration.cs | 2 +- .../Configuration/IReaderConfiguration.cs | 4 +- src/CsvHelper/CsvFieldReader.cs | 4 +- src/CsvHelper/CsvHelper.csproj | 6 +- src/CsvHelper/CsvHelperException.cs | 16 +- src/CsvHelper/CsvParser.cs | 151 +++++------ src/CsvHelper/CsvReader.cs | 6 +- src/CsvHelper/CsvSerializer.cs | 4 +- src/CsvHelper/CsvWriter.cs | 6 +- src/CsvHelper/IFieldReader.cs | 2 +- src/CsvHelper/IParser.cs | 2 +- src/CsvHelper/IReaderRow.cs | 2 +- src/CsvHelper/IReadingContext.cs | 198 --------------- src/CsvHelper/ISerializer.cs | 2 +- src/CsvHelper/IWriterRow.cs | 2 +- src/CsvHelper/IWritingContext.cs | 83 ------ src/CsvHelper/MissingFieldException.cs | 6 +- src/CsvHelper/ParserException.cs | 6 +- src/CsvHelper/ReaderException.cs | 6 +- src/CsvHelper/ReadingContext.cs | 112 ++++---- .../TypeConversion/TypeConverterException.cs | 12 +- src/CsvHelper/ValidationException.cs | 6 +- src/CsvHelper/WriterException.cs | 6 +- src/CsvHelper/WritingContext.cs | 240 +++++++++--------- 32 files changed, 347 insertions(+), 601 deletions(-) delete mode 100644 src/CsvHelper/IReadingContext.cs delete mode 100644 src/CsvHelper/IWritingContext.cs diff --git a/src/CsvHelper.Performance/CsvHelper.Performance.csproj b/src/CsvHelper.Performance/CsvHelper.Performance.csproj index 8b98038a5..c2e1e87a1 100644 --- a/src/CsvHelper.Performance/CsvHelper.Performance.csproj +++ b/src/CsvHelper.Performance/CsvHelper.Performance.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.0 + net45 diff --git a/src/CsvHelper.Performance/Program.cs b/src/CsvHelper.Performance/Program.cs index e4103d9ca..6010c771d 100644 --- a/src/CsvHelper.Performance/Program.cs +++ b/src/CsvHelper.Performance/Program.cs @@ -2,6 +2,7 @@ // This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. // See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. // https://github.com/JoshClose/CsvHelper +using CsvHelper.Configuration; using System; using System.Collections.Generic; using System.Diagnostics; @@ -13,18 +14,18 @@ class Program { static void Main( string[] args ) { + //WriteField( 50, 1000000); + WriteRecords( 1000000 ); + //Parse(); //ReadGetField(); //ReadGetRecords(); - - WriteField( 50, 1000000); - WriteRecords( 1000000 ); } static string GetFilePath() { var homePath = Environment.ExpandEnvironmentVariables( "%HOMEDRIVE%%HOMEPATH%" ); - var filePath = Path.Combine( homePath, "Documents", "large.csv" ); + var filePath = Path.Combine( homePath, "Documents", "performance.csv" ); return filePath; } @@ -200,6 +201,28 @@ static void ReadGetRecords() Console.WriteLine( stopwatch.Elapsed ); } + private class Data + { + public int Id { get; set; } + + public string Name { get; set; } + + public int Age { get; set; } + + public DateTimeOffset Birthday { get; set; } + } + + private class DataMap : ClassMap + { + public DataMap() + { + Map( m => m.Id ).Index( 0 ); + Map( m => m.Name ).Index( 1 ); + Map( m => m.Age ).Index( 2 ); + Map( m => m.Birthday ).Index( 3 ); + } + } + private class Columns50 { public int Column1 { get; set; } diff --git a/src/CsvHelper.Tests/Configuration/ClassMapBuilderTests.cs b/src/CsvHelper.Tests/Configuration/ClassMapBuilderTests.cs index 38d5e16fe..b8416c96b 100644 --- a/src/CsvHelper.Tests/Configuration/ClassMapBuilderTests.cs +++ b/src/CsvHelper.Tests/Configuration/ClassMapBuilderTests.cs @@ -110,7 +110,7 @@ private class BuilderRowFake : IReaderRow public string[] CurrentRecord { get; } public int Row { get; } - public IReadingContext Context + public ReadingContext Context { get { diff --git a/src/CsvHelper.Tests/Mocks/ParserMock.cs b/src/CsvHelper.Tests/Mocks/ParserMock.cs index fd61cbf5a..2afd67f94 100644 --- a/src/CsvHelper.Tests/Mocks/ParserMock.cs +++ b/src/CsvHelper.Tests/Mocks/ParserMock.cs @@ -17,7 +17,7 @@ public class ParserMock : IParser, IEnumerable private readonly Queue rows; private ReadingContext context; - public IReadingContext Context => context; + public ReadingContext Context => context; public IParserConfiguration Configuration { get; } diff --git a/src/CsvHelper.Tests/Mocks/SerializerMock.cs b/src/CsvHelper.Tests/Mocks/SerializerMock.cs index 674345b73..4ec8e19df 100644 --- a/src/CsvHelper.Tests/Mocks/SerializerMock.cs +++ b/src/CsvHelper.Tests/Mocks/SerializerMock.cs @@ -26,7 +26,7 @@ public List Records get { return records; } } - public IWritingContext Context { get; } + public WritingContext Context { get; } public SerializerMock( bool throwExceptionOnWrite = false ) { diff --git a/src/CsvHelper.sln b/src/CsvHelper.sln index 1b8f3cbd8..ae1789c0d 100644 --- a/src/CsvHelper.sln +++ b/src/CsvHelper.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.6 +VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6445B2A3-9E05-4ABF-AE2E-C875773B277A}" ProjectSection(SolutionItems) = preProject @@ -20,7 +20,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CsvHelper", "CsvHelper\CsvH EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CsvHelper.Tests", "CsvHelper.Tests\CsvHelper.Tests.csproj", "{6859ECD8-81AE-4E74-A926-5726AAD7EE81}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsvHelper.Performance", "CsvHelper.Performance\CsvHelper.Performance.csproj", "{9DC1A5EB-4E87-4449-B5B2-241ACD5121E1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CsvHelper.Performance", "CsvHelper.Performance\CsvHelper.Performance.csproj", "{9DC1A5EB-4E87-4449-B5B2-241ACD5121E1}" EndProject Global GlobalSection(Performance) = preSolution @@ -103,4 +103,13 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7F48D3EE-214D-45F4-AC6A-3E95C3A25E9F} + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal diff --git a/src/CsvHelper/BadDataException.cs b/src/CsvHelper/BadDataException.cs index eee028a5e..21465a754 100644 --- a/src/CsvHelper/BadDataException.cs +++ b/src/CsvHelper/BadDataException.cs @@ -16,7 +16,7 @@ public class BadDataException : CsvHelperException /// Initializes a new instance of the class. /// /// The reading context. - public BadDataException( IReadingContext context ) : base( context ) { } + public BadDataException( ReadingContext context ) : base( context ) { } /// /// Initializes a new instance of the class @@ -24,7 +24,7 @@ public BadDataException( IReadingContext context ) : base( context ) { } /// /// The reading context. /// The message that describes the error. - public BadDataException( IReadingContext context, string message ) : base( context, message ) { } + public BadDataException( ReadingContext context, string message ) : base( context, message ) { } /// /// Initializes a new instance of the class @@ -34,6 +34,6 @@ public BadDataException( IReadingContext context, string message ) : base( conte /// The reading context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public BadDataException( IReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } + public BadDataException( ReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } } } diff --git a/src/CsvHelper/Configuration/Configuration.cs b/src/CsvHelper/Configuration/Configuration.cs index 265d3d4b4..024fd0a5a 100644 --- a/src/CsvHelper/Configuration/Configuration.cs +++ b/src/CsvHelper/Configuration/Configuration.cs @@ -50,7 +50,7 @@ public class Configuration : IReaderConfiguration, IWriterConfiguration /// You can supply your own function to do other things like logging the issue instead of throwing an exception. /// Arguments: isValid, headerNames, headerNameIndex, context /// - public virtual Action HeaderValidated { get; set; } = ( isValid, headerNames, headerNameIndex, context ) => + public virtual Action HeaderValidated { get; set; } = ( isValid, headerNames, headerNameIndex, context ) => { if( isValid ) { @@ -72,7 +72,7 @@ public class Configuration : IReaderConfiguration, IWriterConfiguration /// like logging the issue instead of throwing an exception. /// Arguments: headerNames, index, context /// - public virtual Action MissingFieldFound { get; set; } = ( headerNames, index, context ) => + public virtual Action MissingFieldFound { get; set; } = ( headerNames, index, context ) => { var messagePostfix = $"You can ignore missing fields by setting {nameof( MissingFieldFound )} to null."; @@ -91,7 +91,7 @@ public class Configuration : IReaderConfiguration, IWriterConfiguration /// instead of throwing an exception. /// Arguments: context /// - public virtual Action BadDataFound { get; set; } = context => + public virtual Action BadDataFound { get; set; } = context => { throw new BadDataException( context, $"You can ignore bad data by setting {nameof( BadDataFound )} to null." ); }; diff --git a/src/CsvHelper/Configuration/IParserConfiguration.cs b/src/CsvHelper/Configuration/IParserConfiguration.cs index aa13119cc..80853607f 100644 --- a/src/CsvHelper/Configuration/IParserConfiguration.cs +++ b/src/CsvHelper/Configuration/IParserConfiguration.cs @@ -39,7 +39,7 @@ public interface IParserConfiguration /// instead of throwing an exception. /// Arguments: context /// - Action BadDataFound { get; set; } + Action BadDataFound { get; set; } /// /// Gets or sets the character used to denote diff --git a/src/CsvHelper/Configuration/IReaderConfiguration.cs b/src/CsvHelper/Configuration/IReaderConfiguration.cs index e2c4290cf..e050a579d 100644 --- a/src/CsvHelper/Configuration/IReaderConfiguration.cs +++ b/src/CsvHelper/Configuration/IReaderConfiguration.cs @@ -27,7 +27,7 @@ public interface IReaderConfiguration : IParserConfiguration /// You can supply your own function to do other things like logging the issue instead of throwing an exception. /// Arguments: isValid, headerNames, headerNameIndex, context /// - Action HeaderValidated { get; set; } + Action HeaderValidated { get; set; } /// /// Gets or sets the function that is called when a missing field is found. The default function will @@ -35,7 +35,7 @@ public interface IReaderConfiguration : IParserConfiguration /// like logging the issue instead of throwing an exception. /// Arguments: headerNames, index, context /// - Action MissingFieldFound { get; set; } + Action MissingFieldFound { get; set; } /// /// Gets or sets the function that is called when a reading exception occurs. diff --git a/src/CsvHelper/CsvFieldReader.cs b/src/CsvHelper/CsvFieldReader.cs index 1428e2708..8d292ff72 100644 --- a/src/CsvHelper/CsvFieldReader.cs +++ b/src/CsvHelper/CsvFieldReader.cs @@ -19,13 +19,13 @@ namespace CsvHelper /// public partial class CsvFieldReader : IFieldReader { - private IReadingContext context; + private ReadingContext context; private bool disposed; /// /// Gets the reading context. /// - public virtual IReadingContext Context => context; + public virtual ReadingContext Context => context; /// /// Gets a value indicating if the buffer is empty. diff --git a/src/CsvHelper/CsvHelper.csproj b/src/CsvHelper/CsvHelper.csproj index c71a7fe0d..704cd87a1 100644 --- a/src/CsvHelper/CsvHelper.csproj +++ b/src/CsvHelper/CsvHelper.csproj @@ -8,9 +8,9 @@ Josh Close - 6.1.1 - 6.0.0.0 - 6.0.0.0 + 7.0.0 + 7.0.0.0 + 7.0.0.0 netstandard2.0;net45 7.1 true diff --git a/src/CsvHelper/CsvHelperException.cs b/src/CsvHelper/CsvHelperException.cs index 0153701b6..6528d6bb5 100644 --- a/src/CsvHelper/CsvHelperException.cs +++ b/src/CsvHelper/CsvHelperException.cs @@ -16,12 +16,12 @@ public class CsvHelperException : Exception /// /// Gets the context used when reading. /// - public IReadingContext ReadingContext { get; private set; } + public ReadingContext ReadingContext { get; private set; } /// /// Gets the context used when writing. /// - public IWritingContext WritingContext { get; private set; } + public WritingContext WritingContext { get; private set; } /// /// Initializes a new instance of the CsvHelperException class. @@ -44,7 +44,7 @@ internal protected CsvHelperException( string message, Exception innerException /// /// Initializes a new instance of the class. /// - public CsvHelperException( IReadingContext context ) + public CsvHelperException( ReadingContext context ) { ReadingContext = context; } @@ -52,7 +52,7 @@ public CsvHelperException( IReadingContext context ) /// /// Initializes a new instance of the class. /// - public CsvHelperException( IWritingContext context ) + public CsvHelperException( WritingContext context ) { WritingContext = context; } @@ -63,7 +63,7 @@ public CsvHelperException( IWritingContext context ) /// /// The reading context. /// The message that describes the error. - public CsvHelperException( IReadingContext context, string message ) : base( message ) + public CsvHelperException( ReadingContext context, string message ) : base( message ) { ReadingContext = context; } @@ -76,7 +76,7 @@ public CsvHelperException( IReadingContext context, string message ) : base( mes /// The reading context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public CsvHelperException( IReadingContext context, string message, Exception innerException ) : base( message, innerException ) + public CsvHelperException( ReadingContext context, string message, Exception innerException ) : base( message, innerException ) { ReadingContext = context; } @@ -87,7 +87,7 @@ public CsvHelperException( IReadingContext context, string message, Exception in /// /// The writing context. /// The message that describes the error. - public CsvHelperException( IWritingContext context, string message ) : base( message ) + public CsvHelperException( WritingContext context, string message ) : base( message ) { WritingContext = context; } @@ -100,7 +100,7 @@ public CsvHelperException( IWritingContext context, string message ) : base( mes /// The writing context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public CsvHelperException( IWritingContext context, string message, Exception innerException ) : base( message, innerException ) + public CsvHelperException( WritingContext context, string message, Exception innerException ) : base( message, innerException ) { WritingContext = context; } diff --git a/src/CsvHelper/CsvParser.cs b/src/CsvHelper/CsvParser.cs index bd3646df0..9d9ab9646 100644 --- a/src/CsvHelper/CsvParser.cs +++ b/src/CsvHelper/CsvParser.cs @@ -20,14 +20,15 @@ namespace CsvHelper /// public partial class CsvParser : IParser { - private IReadingContext context; + private ReadingContext context; private IFieldReader fieldReader; private bool disposed; + private int c = -1; /// /// Gets the reading context. /// - public virtual IReadingContext Context => context; + public virtual ReadingContext Context => context; /// /// Gets the configuration. @@ -74,7 +75,7 @@ public partial class CsvParser : IParser public CsvParser( IFieldReader fieldReader ) { this.fieldReader = fieldReader ?? throw new ArgumentNullException( nameof( fieldReader ) ); - context = fieldReader.Context as IReadingContext ?? throw new InvalidOperationException( $"For {nameof( FieldReader )} to be used in {nameof( CsvParser )}, {nameof( FieldReader.Context )} must also implement {nameof( IReadingContext )}." ); + context = fieldReader.Context as ReadingContext ?? throw new InvalidOperationException( $"For {nameof( FieldReader )} to be used in {nameof( CsvParser )}, {nameof( FieldReader.Context )} must also implement {nameof( ReadingContext )}." ); } /// @@ -174,9 +175,9 @@ protected virtual string[] ReadLine() return null; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); - if( context.RecordBuilder.Length == 0 && ( ( context.C == context.ParserConfiguration.Comment && context.ParserConfiguration.AllowComments ) || context.C == '\r' || context.C == '\n' ) ) + if( context.RecordBuilder.Length == 0 && ( ( c == context.ParserConfiguration.Comment && context.ParserConfiguration.AllowComments ) || c == '\r' || c == '\n' ) ) { ReadBlankLine(); if( !context.ParserConfiguration.IgnoreBlankLines ) @@ -188,13 +189,13 @@ protected virtual string[] ReadLine() } // Trim start outside of quotes. - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { ReadSpaces(); fieldReader.SetFieldStart( -1 ); } - if( context.C == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) + if( c == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) { if( ReadQuotedField() ) { @@ -239,9 +240,9 @@ protected virtual async Task ReadLineAsync() return null; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); - if( context.RecordBuilder.Length == 0 && ( ( context.C == context.ParserConfiguration.Comment && context.ParserConfiguration.AllowComments ) || context.C == '\r' || context.C == '\n' ) ) + if( context.RecordBuilder.Length == 0 && ( ( c == context.ParserConfiguration.Comment && context.ParserConfiguration.AllowComments ) || c == '\r' || c == '\n' ) ) { await ReadBlankLineAsync(); if( !context.ParserConfiguration.IgnoreBlankLines ) @@ -253,13 +254,13 @@ protected virtual async Task ReadLineAsync() } // Trim start outside of quotes. - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { await ReadSpacesAsync(); fieldReader.SetFieldStart( -1 ); } - if( context.C == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) + if( c == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) { if( await ReadQuotedFieldAsync() ) { @@ -291,7 +292,7 @@ protected virtual void ReadBlankLine() while( true ) { - if( context.C == '\r' || context.C == '\n' ) + if( c == '\r' || c == '\n' ) { ReadLineEnding(); fieldReader.SetFieldStart(); @@ -309,7 +310,7 @@ protected virtual void ReadBlankLine() return; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } } @@ -326,7 +327,7 @@ protected virtual async Task ReadBlankLineAsync() while( true ) { - if( context.C == '\r' || context.C == '\n' ) + if( c == '\r' || c == '\n' ) { await ReadLineEndingAsync(); fieldReader.SetFieldStart(); @@ -344,7 +345,7 @@ protected virtual async Task ReadBlankLineAsync() return; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } } @@ -354,14 +355,14 @@ protected virtual async Task ReadBlankLineAsync() /// True if the end of the line was found, otherwise false. protected virtual bool ReadField() { - if( context.C != context.ParserConfiguration.Delimiter[0] && context.C != '\r' && context.C != '\n' ) + if( c != context.ParserConfiguration.Delimiter[0] && c != '\r' && c != '\n' ) { if( fieldReader.IsBufferEmpty && !fieldReader.FillBuffer() ) { // End of file. fieldReader.SetFieldEnd(); - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { fieldReader.SetFieldStart(); } @@ -370,19 +371,19 @@ protected virtual bool ReadField() return true; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } var inSpaces = false; while( true ) { - if( context.C == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) + if( c == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) { context.IsFieldBad = true; } // Trim end outside of quotes. - if( !inSpaces && context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( !inSpaces && c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { inSpaces = true; fieldReader.SetFieldEnd( -1 ); @@ -390,18 +391,18 @@ protected virtual bool ReadField() fieldReader.SetFieldStart( -1 ); fieldReader.SetRawRecordStart( -1 ); } - else if( inSpaces && context.C != ' ' ) + else if( inSpaces && c != ' ' ) { // Hit a non-space char. // Need to determine if it's the end of the field or another char. inSpaces = false; - if( context.C == context.ParserConfiguration.Delimiter[0] || context.C == '\r' || context.C == '\n' ) + if( c == context.ParserConfiguration.Delimiter[0] || c == '\r' || c == '\n' ) { fieldReader.SetFieldStart( -1 ); } } - if( context.C == context.ParserConfiguration.Delimiter[0] ) + if( c == context.ParserConfiguration.Delimiter[0] ) { fieldReader.SetFieldEnd( -1 ); @@ -413,7 +414,7 @@ protected virtual bool ReadField() return false; } } - else if( context.C == '\r' || context.C == '\n' ) + else if( c == '\r' || c == '\n' ) { // End of line. fieldReader.SetFieldEnd( -1 ); @@ -431,7 +432,7 @@ protected virtual bool ReadField() // End of file. fieldReader.SetFieldEnd(); - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { fieldReader.SetFieldStart(); } @@ -440,7 +441,7 @@ protected virtual bool ReadField() return true; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } } @@ -450,14 +451,14 @@ protected virtual bool ReadField() /// True if the end of the line was found, otherwise false. protected virtual async Task ReadFieldAsync() { - if( context.C != context.ParserConfiguration.Delimiter[0] && context.C != '\r' && context.C != '\n' ) + if( c != context.ParserConfiguration.Delimiter[0] && c != '\r' && c != '\n' ) { if( fieldReader.IsBufferEmpty && !await fieldReader.FillBufferAsync() ) { // End of file. fieldReader.SetFieldEnd(); - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { fieldReader.SetFieldStart(); } @@ -466,19 +467,19 @@ protected virtual async Task ReadFieldAsync() return true; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } var inSpaces = false; while( true ) { - if( context.C == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) + if( c == context.ParserConfiguration.Quote && !context.ParserConfiguration.IgnoreQuotes ) { context.IsFieldBad = true; } // Trim end outside of quotes. - if( !inSpaces && context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( !inSpaces && c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { inSpaces = true; fieldReader.SetFieldEnd( -1 ); @@ -486,18 +487,18 @@ protected virtual async Task ReadFieldAsync() fieldReader.SetFieldStart( -1 ); fieldReader.SetRawRecordStart( -1 ); } - else if( inSpaces && context.C != ' ' ) + else if( inSpaces && c != ' ' ) { // Hit a non-space char. // Need to determine if it's the end of the field or another char. inSpaces = false; - if( context.C == context.ParserConfiguration.Delimiter[0] || context.C == '\r' || context.C == '\n' ) + if( c == context.ParserConfiguration.Delimiter[0] || c == '\r' || c == '\n' ) { fieldReader.SetFieldStart( -1 ); } } - if( context.C == context.ParserConfiguration.Delimiter[0] ) + if( c == context.ParserConfiguration.Delimiter[0] ) { fieldReader.SetFieldEnd( -1 ); @@ -509,7 +510,7 @@ protected virtual async Task ReadFieldAsync() return false; } } - else if( context.C == '\r' || context.C == '\n' ) + else if( c == '\r' || c == '\n' ) { // End of line. fieldReader.SetFieldEnd( -1 ); @@ -527,7 +528,7 @@ protected virtual async Task ReadFieldAsync() // End of file. fieldReader.SetFieldEnd(); - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { fieldReader.SetFieldStart(); } @@ -536,7 +537,7 @@ protected virtual async Task ReadFieldAsync() return true; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } } @@ -555,7 +556,7 @@ protected virtual bool ReadQuotedField() { // 1,"2" ,3 - var cPrev = context.C; + var cPrev = c; if( fieldReader.IsBufferEmpty && !fieldReader.FillBuffer() ) { @@ -565,10 +566,10 @@ protected virtual bool ReadQuotedField() return true; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); // Trim start inside quotes. - if( inQuotes && context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes && cPrev == context.ParserConfiguration.Quote ) + if( inQuotes && c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes && cPrev == context.ParserConfiguration.Quote ) { ReadSpaces(); cPrev = ' '; @@ -576,25 +577,25 @@ protected virtual bool ReadQuotedField() } // Trim end inside of quotes. - if( !inSpaces && context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes ) + if( !inSpaces && c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes ) { inSpaces = true; fieldReader.SetFieldEnd( -1 ); fieldReader.AppendField(); fieldReader.SetFieldStart( -1 ); } - else if( inSpaces && context.C != ' ' ) + else if( inSpaces && c != ' ' ) { // Hit a non-space char. // Need to determine if it's the end of the field or another char. inSpaces = false; - if( context.C == context.ParserConfiguration.Quote ) + if( c == context.ParserConfiguration.Quote ) { fieldReader.SetFieldStart( -1 ); } } - if( context.C == context.ParserConfiguration.Quote ) + if( c == context.ParserConfiguration.Quote ) { inQuotes = !inQuotes; @@ -611,7 +612,7 @@ protected virtual bool ReadQuotedField() if( inQuotes ) { - if( context.C == '\r' || ( context.C == '\n' && cPrev != '\r' ) ) + if( c == '\r' || ( c == '\n' && cPrev != '\r' ) ) { // Inside a quote \r\n is just another character to absorb. context.RawRow++; @@ -621,13 +622,13 @@ protected virtual bool ReadQuotedField() if( !inQuotes ) { // Trim end outside of quotes. - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { ReadSpaces(); fieldReader.SetFieldStart( -1 ); } - if( context.C == context.ParserConfiguration.Delimiter[0] ) + if( c == context.ParserConfiguration.Delimiter[0] ) { fieldReader.SetFieldEnd( -1 ); @@ -638,7 +639,7 @@ protected virtual bool ReadQuotedField() return false; } } - else if( context.C == '\r' || context.C == '\n' ) + else if( c == '\r' || c == '\n' ) { fieldReader.SetFieldEnd( -1 ); var offset = ReadLineEnding(); @@ -672,7 +673,7 @@ protected virtual async Task ReadQuotedFieldAsync() { // 1,"2" ,3 - var cPrev = context.C; + var cPrev = c; if( fieldReader.IsBufferEmpty && !await fieldReader.FillBufferAsync() ) { @@ -682,10 +683,10 @@ protected virtual async Task ReadQuotedFieldAsync() return true; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); // Trim start inside quotes. - if( inQuotes && context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes && cPrev == context.ParserConfiguration.Quote ) + if( inQuotes && c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes && cPrev == context.ParserConfiguration.Quote ) { await ReadSpacesAsync(); cPrev = ' '; @@ -693,25 +694,25 @@ protected virtual async Task ReadQuotedFieldAsync() } // Trim end inside of quotes. - if( !inSpaces && context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes ) + if( !inSpaces && c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.InsideQuotes ) == TrimOptions.InsideQuotes ) { inSpaces = true; fieldReader.SetFieldEnd( -1 ); fieldReader.AppendField(); fieldReader.SetFieldStart( -1 ); } - else if( inSpaces && context.C != ' ' ) + else if( inSpaces && c != ' ' ) { // Hit a non-space char. // Need to determine if it's the end of the field or another char. inSpaces = false; - if( context.C == context.ParserConfiguration.Quote ) + if( c == context.ParserConfiguration.Quote ) { fieldReader.SetFieldStart( -1 ); } } - if( context.C == context.ParserConfiguration.Quote ) + if( c == context.ParserConfiguration.Quote ) { inQuotes = !inQuotes; @@ -728,7 +729,7 @@ protected virtual async Task ReadQuotedFieldAsync() if( inQuotes ) { - if( context.C == '\r' || ( context.C == '\n' && cPrev != '\r' ) ) + if( c == '\r' || ( c == '\n' && cPrev != '\r' ) ) { // Inside a quote \r\n is just another character to absorb. context.RawRow++; @@ -738,13 +739,13 @@ protected virtual async Task ReadQuotedFieldAsync() if( !inQuotes ) { // Trim end outside of quotes. - if( context.C == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) + if( c == ' ' && ( context.ParserConfiguration.TrimOptions & TrimOptions.Trim ) == TrimOptions.Trim ) { await ReadSpacesAsync(); fieldReader.SetFieldStart( -1 ); } - if( context.C == context.ParserConfiguration.Delimiter[0] ) + if( c == context.ParserConfiguration.Delimiter[0] ) { fieldReader.SetFieldEnd( -1 ); @@ -755,7 +756,7 @@ protected virtual async Task ReadQuotedFieldAsync() return false; } } - else if( context.C == '\r' || context.C == '\n' ) + else if( c == '\r' || c == '\n' ) { fieldReader.SetFieldEnd( -1 ); var offset = await ReadLineEndingAsync(); @@ -781,7 +782,7 @@ protected virtual async Task ReadQuotedFieldAsync() /// chars ended up not being the delimiter. protected virtual bool ReadDelimiter() { - if( context.C != context.ParserConfiguration.Delimiter[0] ) + if( c != context.ParserConfiguration.Delimiter[0] ) { throw new InvalidOperationException( "Tried reading a delimiter when the first delimiter char didn't match the current char." ); } @@ -799,8 +800,8 @@ protected virtual bool ReadDelimiter() return false; } - context.C = fieldReader.GetChar(); - if( context.C != context.ParserConfiguration.Delimiter[i] ) + c = fieldReader.GetChar(); + if( c != context.ParserConfiguration.Delimiter[i] ) { return false; } @@ -816,7 +817,7 @@ protected virtual bool ReadDelimiter() /// chars ended up not being the delimiter. protected virtual async Task ReadDelimiterAsync() { - if( context.C != context.ParserConfiguration.Delimiter[0] ) + if( c != context.ParserConfiguration.Delimiter[0] ) { throw new InvalidOperationException( "Tried reading a delimiter when the first delimiter char didn't match the current char." ); } @@ -834,8 +835,8 @@ protected virtual async Task ReadDelimiterAsync() return false; } - context.C = fieldReader.GetChar(); - if( context.C != context.ParserConfiguration.Delimiter[i] ) + c = fieldReader.GetChar(); + if( c != context.ParserConfiguration.Delimiter[i] ) { return false; } @@ -851,7 +852,7 @@ protected virtual async Task ReadDelimiterAsync() protected virtual int ReadLineEnding() { var fieldStartOffset = 0; - if( context.C == '\r' ) + if( c == '\r' ) { if( fieldReader.IsBufferEmpty && !fieldReader.FillBuffer() ) { @@ -859,8 +860,8 @@ protected virtual int ReadLineEnding() return fieldStartOffset; } - context.C = fieldReader.GetChar(); - if( context.C != '\n' && context.C != -1 ) + c = fieldReader.GetChar(); + if( c != '\n' && c != -1 ) { // The start needs to be moved back. fieldStartOffset--; @@ -877,7 +878,7 @@ protected virtual int ReadLineEnding() protected virtual async Task ReadLineEndingAsync() { var fieldStartOffset = 0; - if( context.C == '\r' ) + if( c == '\r' ) { if( fieldReader.IsBufferEmpty && !await fieldReader.FillBufferAsync() ) { @@ -885,8 +886,8 @@ protected virtual async Task ReadLineEndingAsync() return fieldStartOffset; } - context.C = fieldReader.GetChar(); - if( context.C != '\n' && context.C != -1 ) + c = fieldReader.GetChar(); + if( c != '\n' && c != -1 ) { // The start needs to be moved back. fieldStartOffset--; @@ -905,7 +906,7 @@ protected virtual bool ReadSpaces() { while( true ) { - if( context.C != ' ' ) + if( c != ' ' ) { break; } @@ -916,7 +917,7 @@ protected virtual bool ReadSpaces() return false; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } return true; @@ -931,7 +932,7 @@ protected virtual async Task ReadSpacesAsync() { while( true ) { - if( context.C != ' ' ) + if( c != ' ' ) { break; } @@ -942,7 +943,7 @@ protected virtual async Task ReadSpacesAsync() return false; } - context.C = fieldReader.GetChar(); + c = fieldReader.GetChar(); } return true; diff --git a/src/CsvHelper/CsvReader.cs b/src/CsvHelper/CsvReader.cs index 5ad95eff6..bcd4548de 100644 --- a/src/CsvHelper/CsvReader.cs +++ b/src/CsvHelper/CsvReader.cs @@ -24,14 +24,14 @@ namespace CsvHelper public class CsvReader : IReader { private readonly RecordManager recordManager; - private IReadingContext context; + private ReadingContext context; private bool disposed; private IParser parser; /// /// Gets the reading context. /// - public virtual IReadingContext Context => context; + public virtual ReadingContext Context => context; /// /// Gets the configuration. @@ -79,7 +79,7 @@ public class CsvReader : IReader public CsvReader( IParser parser ) { this.parser = parser ?? throw new ArgumentNullException( nameof( parser ) ); - context = parser.Context as IReadingContext ?? throw new InvalidOperationException( $"For {nameof( IParser )} to be used in {nameof( CsvReader )}, {nameof( IParser.Context )} must also implement {nameof( IReadingContext )}." ); + context = parser.Context as ReadingContext ?? throw new InvalidOperationException( $"For {nameof( IParser )} to be used in {nameof( CsvReader )}, {nameof( IParser.Context )} must also implement {nameof( ReadingContext )}." ); recordManager = new RecordManager( this ); } diff --git a/src/CsvHelper/CsvSerializer.cs b/src/CsvHelper/CsvSerializer.cs index 55f078ff2..321e7af4b 100644 --- a/src/CsvHelper/CsvSerializer.cs +++ b/src/CsvHelper/CsvSerializer.cs @@ -15,13 +15,13 @@ namespace CsvHelper /// public class CsvSerializer : ISerializer { - private IWritingContext context; + private WritingContext context; private bool disposed; /// /// Gets the writing context. /// - public virtual IWritingContext Context => context; + public virtual WritingContext Context => context; /// /// Gets the configuration. diff --git a/src/CsvHelper/CsvWriter.cs b/src/CsvHelper/CsvWriter.cs index f0ae6a542..24a5f125d 100644 --- a/src/CsvHelper/CsvWriter.cs +++ b/src/CsvHelper/CsvWriter.cs @@ -30,14 +30,14 @@ namespace CsvHelper public class CsvWriter : IWriter { private readonly RecordManager recordManager; - private IWritingContext context; + private WritingContext context; private bool disposed; private ISerializer serializer; /// /// Gets the writing context. /// - public virtual IWritingContext Context => context; + public virtual WritingContext Context => context; /// /// Gets the configuration. @@ -71,7 +71,7 @@ public class CsvWriter : IWriter public CsvWriter( ISerializer serializer ) { this.serializer = serializer ?? throw new ArgumentNullException( nameof( serializer ) ); - context = serializer.Context as IWritingContext ?? throw new InvalidOperationException( $"For {nameof( ISerializer )} to be used in {nameof( CsvWriter )}, {nameof( ISerializer.Context )} must also implement {nameof( IWritingContext )}." ); + context = serializer.Context as WritingContext ?? throw new InvalidOperationException( $"For {nameof( ISerializer )} to be used in {nameof( CsvWriter )}, {nameof( ISerializer.Context )} must also implement {nameof( WritingContext )}." ); recordManager = ObjectResolver.Current.Resolve( this ); } diff --git a/src/CsvHelper/IFieldReader.cs b/src/CsvHelper/IFieldReader.cs index 7f4eb45cb..f40d09859 100644 --- a/src/CsvHelper/IFieldReader.cs +++ b/src/CsvHelper/IFieldReader.cs @@ -18,7 +18,7 @@ public interface IFieldReader : IDisposable /// /// Gets the reading context. /// - IReadingContext Context { get; } + ReadingContext Context { get; } /// /// Gets a value indicating if the buffer is empty. diff --git a/src/CsvHelper/IParser.cs b/src/CsvHelper/IParser.cs index 2779f5cad..a7f8684d2 100644 --- a/src/CsvHelper/IParser.cs +++ b/src/CsvHelper/IParser.cs @@ -17,7 +17,7 @@ public interface IParser : IDisposable /// /// Gets the reading context. /// - IReadingContext Context { get; } + ReadingContext Context { get; } /// /// Gets the configuration. diff --git a/src/CsvHelper/IReaderRow.cs b/src/CsvHelper/IReaderRow.cs index 021c9cd3d..2ab7c4cdb 100644 --- a/src/CsvHelper/IReaderRow.cs +++ b/src/CsvHelper/IReaderRow.cs @@ -18,7 +18,7 @@ public interface IReaderRow /// /// Gets the reading context. /// - IReadingContext Context { get; } + ReadingContext Context { get; } /// /// Gets or sets the configuration. diff --git a/src/CsvHelper/IReadingContext.cs b/src/CsvHelper/IReadingContext.cs deleted file mode 100644 index f3850dc06..000000000 --- a/src/CsvHelper/IReadingContext.cs +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2009-2017 Josh Close and Contributors -// This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. -// See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. -// https://github.com/JoshClose/CsvHelper -using CsvHelper.Configuration; -using CsvHelper.TypeConversion; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CsvHelper -{ - /// - /// Context used when reading. - /// - public interface IReadingContext : IDisposable - { - /// - /// Gets the raw record builder. - /// - StringBuilder RawRecordBuilder { get; } - - /// - /// Gets the field builder. - /// - StringBuilder FieldBuilder { get; } - - /// - /// Gets the record builder. - /// - RecordBuilder RecordBuilder { get; } - - /// - /// Gets the named indexes. - /// - Dictionary> NamedIndexes { get; } - - /// - /// Getse the named indexes cache. - /// - Dictionary> NamedIndexCache { get; } - - /// - /// Gets the type converter options cache. - /// - Dictionary TypeConverterOptionsCache { get; } - - /// - /// Gets the create record functions. - /// - Dictionary CreateRecordFuncs { get; } - - /// - /// Gets the hydrate record actions. - /// - Dictionary HydrateRecordActions { get; } - - /// - /// Gets the reusable member map data. - /// - MemberMapData ReusableMemberMapData { get; } - - /// - /// Gets the configuration. - /// - IParserConfiguration ParserConfiguration { get; } - - /// - /// Gets the configuration. - /// - IReaderConfiguration ReaderConfiguration { get; } - - /// - /// Gets the that is read from. - /// - TextReader Reader { get; } - - /// - /// Gets a value indicating if the - /// should be left open when disposing. - /// - bool LeaveOpen { get; set; } - - /// - /// Gets the buffer used to store data from the . - /// - char[] Buffer { get; set; } - - /// - /// Gets all the characters of the record including - /// quotes, delimeters, and line endings. - /// - string RawRecord { get; } - - /// - /// Gets the field. - /// - string Field { get; } - - /// - /// Gets the buffer position. - /// - int BufferPosition { get; set; } - - /// - /// Gets the field start position. - /// - int FieldStartPosition { get; set; } - - /// - /// Gets the field end position. - /// - int FieldEndPosition { get; set; } - - /// - /// Gets the raw record start position. - /// - int RawRecordStartPosition { get; set; } - - /// - /// Gets the raw record end position. - /// - int RawRecordEndPosition { get; set; } - - /// - /// Gets the number of characters read from the . - /// - int CharsRead { get; set; } - - /// - /// Gets the character position. - /// - long CharPosition { get; set; } - - /// - /// Gets the byte position. - /// - long BytePosition { get; set; } - - /// - /// Gets a value indicating if the field is bad. - /// True if the field is bad, otherwise false. - /// A field is bad if a quote is found in a field - /// that isn't escaped. - /// - bool IsFieldBad { get; set; } - - /// - /// Gets the record. - /// - string[] Record { get; set; } - - /// - /// Gets the row of the CSV file that the parser is currently on. - /// - int Row { get; set; } - - /// - /// Gets the row of the CSV file that the parser is currently on. - /// This is the actual file row. - /// - int RawRow { get; set; } - - /// - /// Gets the character the field reader is currently on. - /// - int C { get; set; } - - /// - /// Gets a value indicating if reading has begun. - /// - bool HasBeenRead { get; set; } - - /// - /// Gets the header record. - /// - string[] HeaderRecord { get; set; } - - /// - /// Gets the current index. - /// - int CurrentIndex { get; set; } - - /// - /// Gets the column count. - /// - int ColumnCount { get; set; } - - /// - /// Clears the specified caches. - /// - /// The caches to clear. - void ClearCache( Caches cache ); - } -} diff --git a/src/CsvHelper/ISerializer.cs b/src/CsvHelper/ISerializer.cs index 86108b3be..0f2b8fc00 100644 --- a/src/CsvHelper/ISerializer.cs +++ b/src/CsvHelper/ISerializer.cs @@ -17,7 +17,7 @@ public interface ISerializer : IDisposable /// /// Gets the writing context. /// - IWritingContext Context { get; } + WritingContext Context { get; } /// /// Gets the configuration. diff --git a/src/CsvHelper/IWriterRow.cs b/src/CsvHelper/IWriterRow.cs index beef03d5e..862b780f7 100644 --- a/src/CsvHelper/IWriterRow.cs +++ b/src/CsvHelper/IWriterRow.cs @@ -17,7 +17,7 @@ public interface IWriterRow /// /// Gets the writing context. /// - IWritingContext Context { get; } + WritingContext Context { get; } /// /// Gets or sets the configuration. diff --git a/src/CsvHelper/IWritingContext.cs b/src/CsvHelper/IWritingContext.cs deleted file mode 100644 index ad6769783..000000000 --- a/src/CsvHelper/IWritingContext.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2009-2017 Josh Close and Contributors -// This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. -// See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. -// https://github.com/JoshClose/CsvHelper -using CsvHelper.Configuration; -using CsvHelper.TypeConversion; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CsvHelper -{ - /// - /// Context used when writing. - /// - public interface IWritingContext : IDisposable - { - /// - /// Gets the type actions. - /// - Dictionary TypeActions { get; } - - /// - /// Gets the type converter options. - /// - Dictionary TypeConverterOptionsCache { get; } - - /// - /// Gets or sets the reusable member map data. - /// - MemberMapData ReusableMemberMapData { get; set; } - - /// - /// Gets the writer configuration. - /// - IWriterConfiguration WriterConfiguration { get; } - - /// - /// Gets the serializer configuration. - /// - ISerializerConfiguration SerializerConfiguration { get; } - - /// - /// Gets the . - /// - TextWriter Writer { get; } - - /// - /// Gets a value indicating if the - /// should be left open when disposing. - /// - bool LeaveOpen { get; set; } - - /// - /// Gets the current row. - /// - int Row { get; set; } - - /// - /// Get the current record; - /// - List Record { get; } - - /// - /// Gets a value indicating if the header has been written. - /// - bool HasHeaderBeenWritten { get; set; } - - /// - /// Gets a value indicating if a record has been written. - /// - bool HasRecordBeenWritten { get; set; } - - /// - /// Clears the specified caches. - /// - /// The caches to clear. - void ClearCache( Caches cache ); - } -} diff --git a/src/CsvHelper/MissingFieldException.cs b/src/CsvHelper/MissingFieldException.cs index 068827c53..30b4de93b 100644 --- a/src/CsvHelper/MissingFieldException.cs +++ b/src/CsvHelper/MissingFieldException.cs @@ -17,7 +17,7 @@ public class MissingFieldException : ReaderException /// Initializes a new instance of the class. /// /// The reading context. - public MissingFieldException( IReadingContext context ) : base( context ) { } + public MissingFieldException( ReadingContext context ) : base( context ) { } /// /// Initializes a new instance of the class @@ -25,7 +25,7 @@ public MissingFieldException( IReadingContext context ) : base( context ) { } /// /// The reading context. /// The message that describes the error. - public MissingFieldException( IReadingContext context, string message ) : base( context, message ) { } + public MissingFieldException( ReadingContext context, string message ) : base( context, message ) { } /// /// Initializes a new instance of the class @@ -35,6 +35,6 @@ public MissingFieldException( IReadingContext context, string message ) : base( /// The reading context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public MissingFieldException( IReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } + public MissingFieldException( ReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } } } diff --git a/src/CsvHelper/ParserException.cs b/src/CsvHelper/ParserException.cs index a58b73120..1b8911984 100644 --- a/src/CsvHelper/ParserException.cs +++ b/src/CsvHelper/ParserException.cs @@ -16,7 +16,7 @@ public class ParserException : CsvHelperException /// Initializes a new instance of the class. /// /// The reading context. - public ParserException( IReadingContext context ) : base( context ) { } + public ParserException( ReadingContext context ) : base( context ) { } /// /// Initializes a new instance of the class @@ -24,7 +24,7 @@ public ParserException( IReadingContext context ) : base( context ) { } /// /// The reading context. /// The message that describes the error. - public ParserException( IReadingContext context, string message ) : base( context, message ) { } + public ParserException( ReadingContext context, string message ) : base( context, message ) { } /// /// Initializes a new instance of the class @@ -34,6 +34,6 @@ public ParserException( IReadingContext context, string message ) : base( contex /// The reading context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public ParserException( IReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } + public ParserException( ReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } } } diff --git a/src/CsvHelper/ReaderException.cs b/src/CsvHelper/ReaderException.cs index 50d7f064f..1caf17767 100644 --- a/src/CsvHelper/ReaderException.cs +++ b/src/CsvHelper/ReaderException.cs @@ -16,7 +16,7 @@ public class ReaderException : CsvHelperException /// Initializes a new instance of the class. /// /// The reading context. - public ReaderException( IReadingContext context ) : base( context ) { } + public ReaderException( ReadingContext context ) : base( context ) { } /// /// Initializes a new instance of the class @@ -24,7 +24,7 @@ public ReaderException( IReadingContext context ) : base( context ) { } /// /// The reading context. /// The message that describes the error. - public ReaderException( IReadingContext context, string message ) : base( context, message ) { } + public ReaderException( ReadingContext context, string message ) : base( context, message ) { } /// /// Initializes a new instance of the class @@ -34,6 +34,6 @@ public ReaderException( IReadingContext context, string message ) : base( contex /// The reading context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public ReaderException( IReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } + public ReaderException( ReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } } } diff --git a/src/CsvHelper/ReadingContext.cs b/src/CsvHelper/ReadingContext.cs index 9489c3be4..561c9a845 100644 --- a/src/CsvHelper/ReadingContext.cs +++ b/src/CsvHelper/ReadingContext.cs @@ -14,133 +14,111 @@ namespace CsvHelper /// /// CSV reading state. /// - public class ReadingContext : IReadingContext, IDisposable + public class ReadingContext : IDisposable { private bool disposed; - private TextReader reader; private Configuration.Configuration configuration; /// /// Gets the raw record builder. /// - public virtual StringBuilder RawRecordBuilder { get; } = new StringBuilder(); + public StringBuilder RawRecordBuilder = new StringBuilder(); /// /// Gets the field builder. /// - public virtual StringBuilder FieldBuilder { get; } = new StringBuilder(); + public StringBuilder FieldBuilder = new StringBuilder(); /// /// Gets the record builder. /// - public virtual RecordBuilder RecordBuilder { get; } = new RecordBuilder(); + public RecordBuilder RecordBuilder = new RecordBuilder(); /// /// Gets the named indexes. /// - public virtual Dictionary> NamedIndexes { get; } = new Dictionary>(); + public Dictionary> NamedIndexes = new Dictionary>(); /// /// Getse the named indexes cache. /// - public virtual Dictionary> NamedIndexCache { get; } = new Dictionary>(); + public Dictionary> NamedIndexCache = new Dictionary>(); /// /// Gets the type converter options cache. /// - public virtual Dictionary TypeConverterOptionsCache { get; } = new Dictionary(); + public Dictionary TypeConverterOptionsCache = new Dictionary(); /// /// Gets the create record functions. /// - public virtual Dictionary CreateRecordFuncs { get; } = new Dictionary(); + public Dictionary CreateRecordFuncs = new Dictionary(); /// /// Gets the hydrate record actions. /// - public virtual Dictionary HydrateRecordActions { get; } = new Dictionary(); + public Dictionary HydrateRecordActions = new Dictionary(); /// /// Gets the reusable member map data. /// - public virtual MemberMapData ReusableMemberMapData { get; } = new MemberMapData( null ); - - /// - /// Gets the configuration. - /// - public virtual IParserConfiguration ParserConfiguration => configuration; - - /// - /// Gets the configuration. - /// - public virtual IReaderConfiguration ReaderConfiguration => configuration; + public MemberMapData ReusableMemberMapData = new MemberMapData( null ); /// /// Gets the that is read from. /// - public virtual TextReader Reader => reader; + public TextReader Reader; /// /// Gets a value indicating if the /// should be left open when disposing. /// - public virtual bool LeaveOpen { get; set; } + public bool LeaveOpen; /// /// Gets the buffer used to store data from the . /// - public virtual char[] Buffer { get; set; } - - /// - /// Gets all the characters of the record including - /// quotes, delimeters, and line endings. - /// - public virtual string RawRecord => RawRecordBuilder.ToString(); - - /// - /// Gets the field. - /// - public virtual string Field => FieldBuilder.ToString(); + public char[] Buffer; /// /// Gets the buffer position. /// - public virtual int BufferPosition { get; set; } + public int BufferPosition; /// /// Gets the field start position. /// - public virtual int FieldStartPosition { get; set; } + public int FieldStartPosition; /// /// Gets the field end position. /// - public virtual int FieldEndPosition { get; set; } + public int FieldEndPosition; /// /// Gets the raw record start position. /// - public virtual int RawRecordStartPosition { get; set; } + public int RawRecordStartPosition; /// /// Gets the raw record end position. /// - public virtual int RawRecordEndPosition { get; set; } + public int RawRecordEndPosition; /// /// Gets the number of characters read from the . /// - public virtual int CharsRead { get; set; } + public int CharsRead; /// /// Gets the character position. /// - public virtual long CharPosition { get; set; } + public long CharPosition; /// /// Gets the byte position. /// - public virtual long BytePosition { get; set; } + public long BytePosition; /// /// Gets a value indicating if the field is bad. @@ -148,48 +126,64 @@ public class ReadingContext : IReadingContext, IDisposable /// A field is bad if a quote is found in a field /// that isn't escaped. /// - public virtual bool IsFieldBad { get; set; } + public bool IsFieldBad; /// /// Gets the record. /// - public virtual string[] Record { get; set; } + public string[] Record; /// /// Gets the row of the CSV file that the parser is currently on. /// - public virtual int Row { get; set; } + public int Row; /// /// Gets the row of the CSV file that the parser is currently on. /// This is the actual file row. /// - public virtual int RawRow { get; set; } - - /// - /// Gets the character the field reader is currently on. - /// - public virtual int C { get; set; } = -1; + public int RawRow; /// /// Gets a value indicating if reading has begun. /// - public virtual bool HasBeenRead { get; set; } + public bool HasBeenRead; /// /// Gets the header record. /// - public virtual string[] HeaderRecord { get; set; } + public string[] HeaderRecord; /// /// Gets the current index. /// - public virtual int CurrentIndex { get; set; } = -1; + public int CurrentIndex = -1; /// /// Gets the column count. /// - public virtual int ColumnCount { get; set; } + public int ColumnCount; + + /// + /// Gets the configuration. + /// + public IParserConfiguration ParserConfiguration => configuration; + + /// + /// Gets the configuration. + /// + public IReaderConfiguration ReaderConfiguration => configuration; + + /// + /// Gets all the characters of the record including + /// quotes, delimeters, and line endings. + /// + public string RawRecord => RawRecordBuilder.ToString(); + + /// + /// Gets the field. + /// + public string Field => FieldBuilder.ToString(); /// /// Initializes a new instance. @@ -199,7 +193,7 @@ public class ReadingContext : IReadingContext, IDisposable /// A value indicating if the TextReader should be left open when disposing. public ReadingContext( TextReader reader, Configuration.Configuration configuration, bool leaveOpen ) { - this.reader = reader ?? throw new ArgumentNullException( nameof( reader ) ); + Reader = reader ?? throw new ArgumentNullException( nameof( reader ) ); this.configuration = configuration ?? throw new ArgumentNullException( nameof( configuration ) ); LeaveOpen = leaveOpen; Buffer = new char[0]; @@ -255,10 +249,10 @@ protected virtual void Dispose( bool disposing ) if( disposing ) { - reader?.Dispose(); + Reader?.Dispose(); } - reader = null; + Reader = null; disposed = true; } } diff --git a/src/CsvHelper/TypeConversion/TypeConverterException.cs b/src/CsvHelper/TypeConversion/TypeConverterException.cs index 6ba659f02..dd473f866 100644 --- a/src/CsvHelper/TypeConversion/TypeConverterException.cs +++ b/src/CsvHelper/TypeConversion/TypeConverterException.cs @@ -40,7 +40,7 @@ public class TypeConverterException : CsvHelperException /// The member map data. /// The text. /// The reading context. - public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, string text, IReadingContext context ) : base( context ) + public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, string text, ReadingContext context ) : base( context ) { TypeConverter = typeConverter; MemberMapData = memberMapData; @@ -54,7 +54,7 @@ public TypeConverterException( ITypeConverter typeConverter, MemberMapData membe /// The member map data. /// The value. /// The writing context. - public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, object value, IWritingContext context ) : base( context ) + public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, object value, WritingContext context ) : base( context ) { TypeConverter = typeConverter; MemberMapData = memberMapData; @@ -70,7 +70,7 @@ public TypeConverterException( ITypeConverter typeConverter, MemberMapData membe /// The text. /// The reading context. /// The message that describes the error. - public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, string text, IReadingContext context, string message ) : base( context, message ) + public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, string text, ReadingContext context, string message ) : base( context, message ) { TypeConverter = typeConverter; MemberMapData = memberMapData; @@ -86,7 +86,7 @@ public TypeConverterException( ITypeConverter typeConverter, MemberMapData membe /// The value. /// The writing context. /// The message that describes the error. - public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, object value, IWritingContext context, string message ) : base( context, message ) + public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, object value, WritingContext context, string message ) : base( context, message ) { TypeConverter = typeConverter; MemberMapData = memberMapData; @@ -104,7 +104,7 @@ public TypeConverterException( ITypeConverter typeConverter, MemberMapData membe /// The reading context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, string text, IReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) + public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, string text, ReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { TypeConverter = typeConverter; MemberMapData = memberMapData; @@ -122,7 +122,7 @@ public TypeConverterException( ITypeConverter typeConverter, MemberMapData membe /// The writing context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, object value, IWritingContext context, string message, Exception innerException ) : base( context, message, innerException ) + public TypeConverterException( ITypeConverter typeConverter, MemberMapData memberMapData, object value, WritingContext context, string message, Exception innerException ) : base( context, message, innerException ) { TypeConverter = typeConverter; MemberMapData = memberMapData; diff --git a/src/CsvHelper/ValidationException.cs b/src/CsvHelper/ValidationException.cs index 94b6405c4..9867df82a 100644 --- a/src/CsvHelper/ValidationException.cs +++ b/src/CsvHelper/ValidationException.cs @@ -16,7 +16,7 @@ public class ValidationException : CsvHelperException /// Initializes a new instance of the class. /// /// The reading context. - public ValidationException( IReadingContext context ) : base( context ) { } + public ValidationException( ReadingContext context ) : base( context ) { } /// /// Initializes a new instance of the class @@ -24,7 +24,7 @@ public ValidationException( IReadingContext context ) : base( context ) { } /// /// The reading context. /// The message that describes the error. - public ValidationException( IReadingContext context, string message ) : base( context, message ) { } + public ValidationException( ReadingContext context, string message ) : base( context, message ) { } /// /// Initializes a new instance of the class @@ -34,6 +34,6 @@ public ValidationException( IReadingContext context, string message ) : base( co /// The reading context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public ValidationException( IReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } + public ValidationException( ReadingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } } } diff --git a/src/CsvHelper/WriterException.cs b/src/CsvHelper/WriterException.cs index b679002e6..69590fa54 100644 --- a/src/CsvHelper/WriterException.cs +++ b/src/CsvHelper/WriterException.cs @@ -16,7 +16,7 @@ public class WriterException : CsvHelperException /// Initializes a new instance of the class. /// /// The writing context. - public WriterException( IWritingContext context ) : base( context ) { } + public WriterException( WritingContext context ) : base( context ) { } /// /// Initializes a new instance of the class @@ -24,7 +24,7 @@ public WriterException( IWritingContext context ) : base( context ) { } /// /// The writing context. /// The message that describes the error. - public WriterException( IWritingContext context, string message ) : base( context, message ) { } + public WriterException( WritingContext context, string message ) : base( context, message ) { } /// /// Initializes a new instance of the class @@ -34,6 +34,6 @@ public WriterException( IWritingContext context, string message ) : base( contex /// The writing context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - public WriterException( IWritingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } + public WriterException( WritingContext context, string message, Exception innerException ) : base( context, message, innerException ) { } } } diff --git a/src/CsvHelper/WritingContext.cs b/src/CsvHelper/WritingContext.cs index 4ffda5953..77df3d394 100644 --- a/src/CsvHelper/WritingContext.cs +++ b/src/CsvHelper/WritingContext.cs @@ -1,22 +1,22 @@ -// Copyright 2009-2017 Josh Close and Contributors -// This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. -// See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. -// https://github.com/JoshClose/CsvHelper -using CsvHelper.Configuration; -using CsvHelper.TypeConversion; -using System; -using System.Collections.Generic; -using System.IO; - -namespace CsvHelper -{ - /// - /// CSV writing state. - /// - public class WritingContext : IWritingContext, IDisposable - { - private bool disposed; - private TextWriter writer; +// Copyright 2009-2017 Josh Close and Contributors +// This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. +// See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. +// https://github.com/JoshClose/CsvHelper +using CsvHelper.Configuration; +using CsvHelper.TypeConversion; +using System; +using System.Collections.Generic; +using System.IO; + +namespace CsvHelper +{ + /// + /// CSV writing state. + /// + public class WritingContext : IDisposable + { + private bool disposed; + private TextWriter writer; private Configuration.Configuration configuration; /// @@ -26,113 +26,113 @@ public class WritingContext : IWritingContext, IDisposable /// /// Gets the type converter options. - /// + /// public Dictionary TypeConverterOptionsCache { get; } = new Dictionary(); /// /// Gets or sets the reusable member map data. - /// - public MemberMapData ReusableMemberMapData { get; set; } = new MemberMapData( null ); - - /// - /// Gets the writer configuration. - /// - public virtual IWriterConfiguration WriterConfiguration => configuration; - - /// - /// Gets the serializer configuration. - /// - public virtual ISerializerConfiguration SerializerConfiguration => configuration; - - /// - /// Gets the . - /// - public virtual TextWriter Writer => writer; - - /// - /// Gets a value indicating if the - /// should be left open when disposing. - /// - public virtual bool LeaveOpen { get; set; } - - /// - /// Gets the current row. - /// - public virtual int Row { get; set; } = 1; - - /// - /// Get the current record; - /// - public virtual List Record { get; } = new List(); - - /// - /// Gets a value indicating if the header has been written. - /// - public virtual bool HasHeaderBeenWritten { get; set; } - - /// - /// Gets a value indicating if a record has been written. - /// - public virtual bool HasRecordBeenWritten { get; set; } - + /// + public MemberMapData ReusableMemberMapData { get; set; } = new MemberMapData( null ); + + /// + /// Gets the writer configuration. + /// + public virtual IWriterConfiguration WriterConfiguration => configuration; + + /// + /// Gets the serializer configuration. + /// + public virtual ISerializerConfiguration SerializerConfiguration => configuration; + + /// + /// Gets the . + /// + public virtual TextWriter Writer => writer; + + /// + /// Gets a value indicating if the + /// should be left open when disposing. + /// + public virtual bool LeaveOpen { get; set; } + + /// + /// Gets the current row. + /// + public virtual int Row { get; set; } = 1; + + /// + /// Get the current record; + /// + public virtual List Record { get; } = new List(); + + /// + /// Gets a value indicating if the header has been written. + /// + public virtual bool HasHeaderBeenWritten { get; set; } + + /// + /// Gets a value indicating if a record has been written. + /// + public virtual bool HasRecordBeenWritten { get; set; } + /// /// Initializes a new instance. /// /// The writer. /// The configuration. - /// A value indicating if the TextWriter should be left open. - public WritingContext( TextWriter writer, Configuration.Configuration configuration, bool leaveOpen ) - { - this.writer = writer ?? throw new ArgumentNullException( nameof( writer ) ); - this.configuration = configuration ?? throw new ArgumentNullException( nameof( configuration ) ); - LeaveOpen = leaveOpen; - } - - /// - /// Clears the specified caches. - /// - /// The caches to clear. - public void ClearCache( Caches cache ) - { - if( ( cache & Caches.TypeConverterOptions ) == Caches.TypeConverterOptions ) - { - TypeConverterOptionsCache.Clear(); - } - - if( ( cache & Caches.WriteRecord ) == Caches.WriteRecord ) - { - TypeActions.Clear(); - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - /// 2 - public virtual void Dispose() - { - Dispose( true ); - GC.SuppressFinalize( this ); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - /// True if the instance needs to be disposed of. - protected virtual void Dispose( bool disposing ) - { - if( disposed ) - { - return; - } - - if( disposing ) - { - writer?.Dispose(); - } - - writer = null; - disposed = true; - } - } -} + /// A value indicating if the TextWriter should be left open. + public WritingContext( TextWriter writer, Configuration.Configuration configuration, bool leaveOpen ) + { + this.writer = writer ?? throw new ArgumentNullException( nameof( writer ) ); + this.configuration = configuration ?? throw new ArgumentNullException( nameof( configuration ) ); + LeaveOpen = leaveOpen; + } + + /// + /// Clears the specified caches. + /// + /// The caches to clear. + public void ClearCache( Caches cache ) + { + if( ( cache & Caches.TypeConverterOptions ) == Caches.TypeConverterOptions ) + { + TypeConverterOptionsCache.Clear(); + } + + if( ( cache & Caches.WriteRecord ) == Caches.WriteRecord ) + { + TypeActions.Clear(); + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public virtual void Dispose() + { + Dispose( true ); + GC.SuppressFinalize( this ); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// True if the instance needs to be disposed of. + protected virtual void Dispose( bool disposing ) + { + if( disposed ) + { + return; + } + + if( disposing ) + { + writer?.Dispose(); + } + + writer = null; + disposed = true; + } + } +}