From 54b25dcae4d18a64df7dff1d3e798e5e0cc880ef Mon Sep 17 00:00:00 2001 From: Josh Close Date: Wed, 19 Jun 2024 08:08:14 -0500 Subject: [PATCH] wip --- .../Configuration/ConfigurationFunctions.cs | 1 - .../Configuration/CsvConfiguration.cs | 330 ------------------ src/CsvHelper/Configuration/CsvOptions.cs | 72 +++- .../Configuration/CsvParserOptions.cs | 54 --- .../Configuration/CsvSerializerOptions.cs | 20 -- .../Configuration/IParserConfiguration.cs | 173 --------- src/CsvHelper/Configuration/IParserOptions.cs | 13 + .../Configuration/IReaderConfiguration.cs | 103 ------ src/CsvHelper/Configuration/IReaderOptions.cs | 8 + .../Configuration/IReadingOptions.cs | 8 + .../Configuration/ISerializerOptions.cs | 8 + .../Configuration/IWriterConfiguration.cs | 165 --------- src/CsvHelper/Configuration/IWriterOptions.cs | 8 + .../Configuration/IWritingOptions.cs | 8 + src/CsvHelper/CsvParser.cs | 67 ++-- src/CsvHelper/CsvParserState.cs | 4 +- src/CsvHelper/CsvReader.cs | 152 ++++---- src/CsvHelper/Delegates/GetDelimiter.cs | 4 +- src/CsvHelper/IParser.cs | 2 + .../ParsingStrategyFactory.cs | 2 +- 20 files changed, 235 insertions(+), 967 deletions(-) delete mode 100644 src/CsvHelper/Configuration/CsvConfiguration.cs delete mode 100644 src/CsvHelper/Configuration/CsvParserOptions.cs delete mode 100644 src/CsvHelper/Configuration/CsvSerializerOptions.cs delete mode 100644 src/CsvHelper/Configuration/IParserConfiguration.cs create mode 100644 src/CsvHelper/Configuration/IParserOptions.cs delete mode 100644 src/CsvHelper/Configuration/IReaderConfiguration.cs create mode 100644 src/CsvHelper/Configuration/IReaderOptions.cs create mode 100644 src/CsvHelper/Configuration/IReadingOptions.cs create mode 100644 src/CsvHelper/Configuration/ISerializerOptions.cs delete mode 100644 src/CsvHelper/Configuration/IWriterConfiguration.cs create mode 100644 src/CsvHelper/Configuration/IWriterOptions.cs create mode 100644 src/CsvHelper/Configuration/IWritingOptions.cs diff --git a/src/CsvHelper/Configuration/ConfigurationFunctions.cs b/src/CsvHelper/Configuration/ConfigurationFunctions.cs index a71f946ee..b2ad9d014 100644 --- a/src/CsvHelper/Configuration/ConfigurationFunctions.cs +++ b/src/CsvHelper/Configuration/ConfigurationFunctions.cs @@ -2,7 +2,6 @@ // 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.Delegates; using System.Reflection; using System.Text; using System.Text.RegularExpressions; diff --git a/src/CsvHelper/Configuration/CsvConfiguration.cs b/src/CsvHelper/Configuration/CsvConfiguration.cs deleted file mode 100644 index 6051aef52..000000000 --- a/src/CsvHelper/Configuration/CsvConfiguration.cs +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2009-2024 Josh Close -// 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.Attributes; -using CsvHelper.Delegates; -using System.Globalization; -using System.Reflection; -using System.Text; - -namespace CsvHelper.Configuration; - -/// -/// Configuration used for reading and writing CSV data. -/// -public record CsvConfiguration : IReaderConfiguration, IWriterConfiguration -{ - private string newLine = "\r\n"; - - /// - public virtual bool AllowComments { get; set; } - - /// - public virtual BadDataFound BadDataFound { get; set; } = ConfigurationFunctions.BadDataFound; - - /// - public virtual int BufferSize { get; set; } = 0x1000; - - /// - public virtual bool CacheFields { get; set; } - - /// - public virtual char Comment { get; set; } = '#'; - - /// - public virtual bool CountBytes { get; set; } - - /// - public virtual CultureInfo CultureInfo { get; protected internal set; } - - /// - public virtual string Delimiter { get; set; } - - /// - public virtual bool DetectDelimiter { get; set; } - - /// - public virtual GetDelimiter GetDelimiter { get; set; } = ConfigurationFunctions.GetDelimiter; - - /// - public virtual string[] DetectDelimiterValues { get; set; } = [",", ";", "|", "\t"]; - - /// - public virtual bool DetectColumnCountChanges { get; set; } - - /// - public virtual IComparer? DynamicPropertySort { get; set; } - - /// - public virtual Encoding Encoding { get; set; } = Encoding.UTF8; - - /// - public virtual char Escape { get; set; } = '"'; - - /// - public virtual bool ExceptionMessagesContainRawData { get; set; } = true; - - /// - public virtual GetConstructor GetConstructor { get; set; } = ConfigurationFunctions.GetConstructor; - - /// - public virtual GetDynamicPropertyName GetDynamicPropertyName { get; set; } = ConfigurationFunctions.GetDynamicPropertyName; - - /// - public virtual bool HasHeaderRecord { get; set; } = true; - - /// - public virtual HeaderValidated HeaderValidated { get; set; } = ConfigurationFunctions.HeaderValidated; - - /// - public virtual bool IgnoreBlankLines { get; set; } = true; - - /// - public virtual bool IgnoreReferences { get; set; } - - /// - public virtual bool IncludePrivateMembers { get; set; } - - /// - public virtual char[] InjectionCharacters { get; set; } = ['=', '@', '+', '-', '\t', '\r']; - - /// - public virtual char InjectionEscapeCharacter { get; set; } = '\''; - - /// - public virtual InjectionOptions InjectionOptions { get; set; } - - /// - public bool IsNewLineSet { get; private set; } - - /// - public virtual bool LineBreakInQuotedFieldIsBadData { get; set; } - - /// - public double MaxFieldSize { get; set; } - - /// - public virtual MemberTypes MemberTypes { get; set; } = MemberTypes.Properties; - - /// - public virtual MissingFieldFound MissingFieldFound { get; set; } = ConfigurationFunctions.MissingFieldFound; - - /// - public virtual CsvMode Mode { get; set; } - - /// - public virtual string NewLine - { - get => newLine; - set - { - IsNewLineSet = true; - newLine = value; - } - } - - /// - public virtual PrepareHeaderForMatch PrepareHeaderForMatch { get; set; } = ConfigurationFunctions.PrepareHeaderForMatch; - - /// - public virtual int ProcessFieldBufferSize { get; set; } = 1024; - - /// - public virtual char Quote { get; set; } = '"'; - - /// - public virtual ReadingExceptionOccurred ReadingExceptionOccurred { get; set; } = ConfigurationFunctions.ReadingExceptionOccurred; - - /// - public virtual ReferenceHeaderPrefix? ReferenceHeaderPrefix { get; set; } - - /// - public ShouldQuote ShouldQuote { get; set; } = ConfigurationFunctions.ShouldQuote; - - /// - public virtual ShouldSkipRecord? ShouldSkipRecord { get; set; } - - /// - public virtual ShouldUseConstructorParameters ShouldUseConstructorParameters { get; set; } = ConfigurationFunctions.ShouldUseConstructorParameters; - - /// - public virtual TrimOptions TrimOptions { get; set; } - - /// - public virtual bool UseNewObjectForNullReferenceMembers { get; set; } = true; - - /// - public virtual char[] WhiteSpaceChars { get; set; } = [' ']; - - /// - /// Initializes a new instance of the class - /// using the given . Since - /// uses for its default, the given - /// will be used instead. - /// - /// The culture information. - public CsvConfiguration(CultureInfo cultureInfo) - { - CultureInfo = cultureInfo; - Delimiter = cultureInfo.TextInfo.ListSeparator; - } - - /// - /// Initializes a new instance of the class - /// using the given . Since - /// uses for its default, the given - /// will be used instead. - /// - /// The culture information. - /// The type that contains the configuration attributes. - /// This will call automatically. - [Obsolete("This constructor is deprecated and will be removed in the next major release. Use CsvConfiguration(CultureInfo) instead.", false)] - public CsvConfiguration(CultureInfo cultureInfo, Type attributesType) - { - CultureInfo = cultureInfo; - Delimiter = cultureInfo.TextInfo.ListSeparator; - - ApplyAttributes(attributesType); - } - - /// - /// Validates the configuration. - /// - public void Validate() - { - var escape = Escape.ToString(); - var quote = Quote.ToString(); - var lineEndings = new[] { "\r", "\n", "\r\n" }; - var whiteSpaceChars = WhiteSpaceChars.Select(c => c.ToString()).ToArray(); - - // Escape - if (escape == Delimiter) throw new ConfigurationException($"The escape character '{Escape}' and delimiter '{Delimiter}' cannot be the same."); - if (escape == NewLine && IsNewLineSet) throw new ConfigurationException($"The escape character '{Escape}' and new line '{NewLine}' cannot be the same."); - if (lineEndings.Contains(Escape.ToString()) && !IsNewLineSet) throw new ConfigurationException($"The escape character '{Escape}' cannot be a line ending. ('\\r', '\\n', '\\r\\n')"); - if (whiteSpaceChars.Contains(escape)) throw new ConfigurationException($"The escape character '{Escape}' cannot be a WhiteSpaceChar."); - - // Quote - if (quote == Delimiter) throw new ConfigurationException($"The quote character '{Quote}' and the delimiter '{Delimiter}' cannot be the same."); - if (quote == NewLine && IsNewLineSet) throw new ConfigurationException($"The quote character '{Quote}' and new line '{NewLine}' cannot be the same."); - if (lineEndings.Contains(quote)) throw new ConfigurationException($"The quote character '{Quote}' cannot be a line ending. ('\\r', '\\n', '\\r\\n')"); - if (whiteSpaceChars.Contains(quote)) throw new ConfigurationException($"The quote character '{Quote}' cannot be a WhiteSpaceChar."); - - // Delimiter - if (Delimiter == NewLine && IsNewLineSet) throw new ConfigurationException($"The delimiter '{Delimiter}' and new line '{NewLine}' cannot be the same."); - if (lineEndings.Contains(Delimiter)) throw new ConfigurationException($"The delimiter '{Delimiter}' cannot be a line ending. ('\\r', '\\n', '\\r\\n')"); - if (whiteSpaceChars.Contains(Delimiter)) throw new ConfigurationException($"The delimiter '{Delimiter}' cannot be a WhiteSpaceChar."); - - // Detect Delimiter - if (DetectDelimiter && DetectDelimiterValues.Length == 0) throw new ConfigurationException($"At least one value is required for {nameof(DetectDelimiterValues)} when {nameof(DetectDelimiter)} is enabled."); - } - - /// - /// Applies class level attribute to configuration. - /// - /// Type with attributes. - public CsvConfiguration ApplyAttributes() - { - return ApplyAttributes(typeof(T)); - } - - /// - /// Applies class level attribute to configuration. - /// - /// Type with attributes. - public CsvConfiguration ApplyAttributes(Type type) - { - var attributes = type.GetCustomAttributes().OfType(); - foreach (var attribute in attributes) - { - attribute.ApplyTo(this); - } - - return this; - } - - /// - /// Creates a instance configured using CsvHelper attributes applied - /// to at the type-level. This method requires to - /// be annotated with (or to sub-class a type which is). - /// - /// - /// The type whose attributes should be used to configure the instance. - /// This is normally the type you are intending to map for reading and writing. - /// - /// A new instance configured with attributes applied to . - /// - /// CsvHelper attributes applied to members and parameters do not influence the return value of this method. - /// Such attributes do not define values which are used in and instead influence - /// the maps which are built and used during reading and writing. See and . - /// - /// If is not annotated with . - /// If the argument to the is . - /// If the argument to the does not specify a supported culture. - public static CsvConfiguration FromAttributes() - { - return FromAttributes(typeof(T)); - } - - /// - /// Creates a instance configured using - /// and CsvHelper attributes applied to at the type-level. - /// This method ignores any applied to . - /// - /// - /// The to configure the returned with. - /// A new instance configured with and attributes applied to . - /// - public static CsvConfiguration FromAttributes(CultureInfo cultureInfo) - { - return FromAttributes(typeof(T), cultureInfo); - } - - /// - /// Creates a instance configured using CsvHelper attributes applied - /// to at the type-level. This method requires to - /// be annotated with (or to sub-class a type which is). - /// - /// - /// A new instance configured with attributes applied to . - /// - /// CsvHelper attributes applied to members and parameters do not influence the return value of this method. - /// Such attributes do not define values which are used in and instead influence - /// the maps which are built and used during reading and writing. See and . - /// - /// If is not annotated with . - /// If the argument to the is . - /// If the argument to the does not specify a supported culture. - public static CsvConfiguration FromAttributes(Type type) - { - var cultureInfoAttribute = (CultureInfoAttribute?)Attribute.GetCustomAttribute(type, typeof(CultureInfoAttribute)); - if (cultureInfoAttribute == null) - { - throw new ConfigurationException($"A {nameof(CultureInfoAttribute)} is required on type '{type.Name}' to use this method."); - } - - var config = new CsvConfiguration(CultureInfo.InvariantCulture); - config.ApplyAttributes(type); - - return config; - } - - /// - /// Creates a instance configured using - /// and CsvHelper attributes applied to at the type-level. - /// This method ignores any applied to . - /// - /// - /// - /// A new instance configured with and attributes applied to - /// - public static CsvConfiguration FromAttributes(Type type, CultureInfo cultureInfo) - { - var config = new CsvConfiguration(cultureInfo); - config.ApplyAttributes(type); - // Override the attribute. - config.CultureInfo = cultureInfo; - - return config; - } -} diff --git a/src/CsvHelper/Configuration/CsvOptions.cs b/src/CsvHelper/Configuration/CsvOptions.cs index b0bbd77bf..1e2a7edfe 100644 --- a/src/CsvHelper/Configuration/CsvOptions.cs +++ b/src/CsvHelper/Configuration/CsvOptions.cs @@ -1,15 +1,23 @@ -namespace CsvHelper.Configuration; +using System.Globalization; + +namespace CsvHelper.Configuration; + +/// +/// A function that is used to determine if a field should get escaped when writing. +/// +/// The field. +public delegate bool ShouldEscape(ReadOnlySpan field); /// /// Common configuration options for reading and writing CSV files. /// -public abstract record CsvOptions +public record CsvOptions : IReadingOptions, IWritingOptions { /// - /// The mode. - /// See for more details. + /// Cache fields that are created when parsing. + /// Default is false. /// - public CsvMode Mode { get; init; } + public bool CacheFields { get; init; } /// /// The delimiter used to separate fields. @@ -18,12 +26,29 @@ public abstract record CsvOptions /// public char Delimiter { get; internal set; } = ','; + /// + /// Detect the delimiter instead of using the delimiter from configuration. + /// Default is false. + /// + public bool DetectDelimiter { get; init; } + /// /// The character used to escape characters. /// Default is '"'. /// public char Escape { get; init; } = '\"'; + /// + /// The function that is called when is enabled. + /// + public GetDelimiter GetDelimiter { get; set; } = ConfigurationFunctions.GetDelimiter; + + /// + /// The mode. + /// See for more details. + /// + public CsvMode Mode { get; init; } + /// /// The newline character to use. /// If not set, the parser uses one of \r\n, \r, or \n. @@ -31,8 +56,45 @@ public abstract record CsvOptions /// public char? NewLine { get; init; } + /// + /// Strategy used for parsing. + /// Defaults to the highest performance your framework and CPU supports. + /// + public ParsingStrategy? ParsingStrategy { get; init; } + + /// + /// A function that is used to determine if a field should get escaped when writing. + /// + public ShouldEscape? ShouldEscape { get; init; } + internal int BufferSize = 0x1000; + internal CsvModeEscape ModeEscape = ModeRfc4180.Escape; + + internal CsvModeParse ModeParse = ModeRfc4180.Parse; + + internal int ParsedFieldsSize = 8 * 32; + + internal int ParsedRowsSize = 8; + + internal ICsvParsingStrategy ParsingStrategyImplementation = new ThrowParsingStrategy(); + + internal StringCreator StringCreator = (chars, i) +#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + => new string(chars); +#else + => chars.ToString(); +#endif + + internal char[] ValidSpecialCharsForIntrinsics = Enumerable + .Range(32, 127 - 32) + .Select(i => (char)i) + .ToList() + .Append('\t') + .Append('\r') + .Append('\n') + .ToArray(); + internal void Validate() { if (Delimiter == Escape) diff --git a/src/CsvHelper/Configuration/CsvParserOptions.cs b/src/CsvHelper/Configuration/CsvParserOptions.cs deleted file mode 100644 index 289b1c677..000000000 --- a/src/CsvHelper/Configuration/CsvParserOptions.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace CsvHelper.Configuration; - -/// -/// Configuration options used for . -/// -public record CsvParserOptions : CsvOptions -{ - /// - /// Cache fields that are created when parsing. - /// Default is false. - /// - public bool CacheFields { get; init; } - - /// - /// Strategy used for parsing. - /// Defaults to the highest performance your framework and CPU supports. - /// - public ParsingStrategy? ParsingStrategy { get; init; } - - /// - /// Detect the delimiter instead of using the delimiter from configuration. - /// Default is false. - /// - public bool DetectDelimiter { get; init; } - - /// - /// The function that is called when is enabled. - /// - public GetDelimiter GetDelimiter { get; set; } = ConfigurationFunctions.GetDelimiter; - - internal StringCreator StringCreator = (chars, i) -#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER - => new string(chars); -#else - => chars.ToString(); -#endif - - internal int ParsedRowsSize = 8; - - internal int ParsedFieldsSize = 8 * 32; - - internal CsvModeParse ModeParse = ModeRfc4180.Parse; - - internal ICsvParsingStrategy ParsingStrategyImplementation = new ThrowParsingStrategy(); - - internal char[] ValidSpecialCharsForIntrinsics = Enumerable - .Range(32, 127 - 32) - .Select(i => (char)i) - .ToList() - .Append('\t') - .Append('\r') - .Append('\n') - .ToArray(); -} diff --git a/src/CsvHelper/Configuration/CsvSerializerOptions.cs b/src/CsvHelper/Configuration/CsvSerializerOptions.cs deleted file mode 100644 index 9e466219f..000000000 --- a/src/CsvHelper/Configuration/CsvSerializerOptions.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace CsvHelper.Configuration; - -/// -/// A function that is used to determine if a field should get escaped when writing. -/// -/// The field. -public delegate bool ShouldEscape(ReadOnlySpan field); - -/// -/// Configuration options used for . -/// -public record CsvSerializerOptions : CsvOptions -{ - /// - /// A function that is used to determine if a field should get escaped when writing. - /// - public ShouldEscape? ShouldEscape { get; init; } - - internal CsvModeEscape ModeEscape = ModeRfc4180.Escape; -} diff --git a/src/CsvHelper/Configuration/IParserConfiguration.cs b/src/CsvHelper/Configuration/IParserConfiguration.cs deleted file mode 100644 index f61df8ce8..000000000 --- a/src/CsvHelper/Configuration/IParserConfiguration.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2009-2024 Josh Close -// 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.Delegates; -using System.Globalization; -using System.Text; - -namespace CsvHelper.Configuration; - -/// -/// Configuration used for the . -/// -public interface IParserConfiguration -{ - /// - /// Gets the culture info used to read an write CSV files. - /// - CultureInfo CultureInfo { get; } - - /// - /// Cache fields that are created when parsing. - /// Default is false. - /// - bool CacheFields { get; } - - /// - /// The newline string to use. Default is \r\n (CRLF). - /// When writing, this value is always used. - /// When reading, this value is only used if explicitly set. - /// If not set, the parser uses one of \r\n, \r, or \n. - /// - string NewLine { get; } - - /// - /// A value indicating if was set. - /// - /// - /// true if was set. false if is the default. - /// - bool IsNewLineSet { get; } - - /// - /// The mode. - /// See for more details. - /// - CsvMode Mode { get; } - - /// - /// Gets the size of the buffer - /// used for parsing and writing CSV files. - /// Default is 0x1000. - /// - int BufferSize { get; } - - /// - /// The size of the buffer used when processing fields. - /// Default is 1024. - /// - int ProcessFieldBufferSize { get; } - - /// - /// Gets a value indicating whether the number of bytes should - /// be counted while parsing. Default is false. This will slow down parsing - /// because it needs to get the byte count of every char for the given encoding. - /// The needs to be set correctly for this to be accurate. - /// - bool CountBytes { get; } - - /// - /// Gets the encoding used when counting bytes. - /// - Encoding Encoding { get; } - - /// - /// Gets the function that is called when bad field data is found. A field - /// has bad data if it contains a quote and the field is not quoted (escaped). - /// You can supply your own function to do other things like logging the issue - /// instead of throwing an exception. - /// - BadDataFound BadDataFound { get; } - - /// - /// Gets or sets the maximum size of a field. - /// Defaults to 0, indicating maximum field size is not checked. - /// - double MaxFieldSize { get; } - - /// - /// Gets a value indicating if a line break found in a quote field should - /// be considered bad data. true to consider a line break bad data, otherwise false. - /// Defaults to false. - /// - bool LineBreakInQuotedFieldIsBadData { get; } - - /// - /// Gets the character used to denote - /// a line that is commented out. Default is '#'. - /// - char Comment { get; } - - /// - /// Gets a value indicating if comments are allowed. - /// true to allow commented out lines, otherwise false. - /// - bool AllowComments { get; } - - /// - /// Gets a value indicating if blank lines - /// should be ignored when reading. - /// true to ignore, otherwise false. Default is true. - /// - bool IgnoreBlankLines { get; } - - /// - /// Gets the character used to quote fields. - /// Default is '"'. - /// - char Quote { get; } - - /// - /// The delimiter used to separate fields. - /// Default is . - /// - char Delimiter { get; } - - /// - /// Detect the delimiter instead of using the delimiter from configuration. - /// Default is false. - /// - bool DetectDelimiter { get; } - - /// - /// Gets the function that is called when is enabled. - /// - GetDelimiter GetDelimiter { get; } - - /// - /// The possible delimiter values used when detecting the delimiter. - /// Default is [",", ";", "|", "\t"]. - /// - char[] DetectDelimiterValues { get; } - - /// - /// The character used to escape characters. - /// Default is '"'. - /// - char Escape { get; } - - /// - /// Gets the field trimming options. - /// - TrimOptions TrimOptions { get; } - - /// - /// Characters considered whitespace. - /// Used when trimming fields. - /// Default is [' ']. - /// - char[] WhiteSpaceChars { get; } - - /// - /// A value indicating if exception messages contain raw CSV data. - /// true if exception contain raw CSV data, otherwise false. - /// Default is true. - /// - bool ExceptionMessagesContainRawData { get; } - - /// - /// Validates the configuration. - /// - void Validate(); -} diff --git a/src/CsvHelper/Configuration/IParserOptions.cs b/src/CsvHelper/Configuration/IParserOptions.cs new file mode 100644 index 000000000..a064001cc --- /dev/null +++ b/src/CsvHelper/Configuration/IParserOptions.cs @@ -0,0 +1,13 @@ +namespace CsvHelper.Configuration; + +/// +/// Options for . +/// +public interface IParserOptions +{ + /// + /// Detect the delimiter instead of using the delimiter from configuration. + /// Default is false. + /// + public bool DetectDelimiter { get; } +} diff --git a/src/CsvHelper/Configuration/IReaderConfiguration.cs b/src/CsvHelper/Configuration/IReaderConfiguration.cs deleted file mode 100644 index e02359099..000000000 --- a/src/CsvHelper/Configuration/IReaderConfiguration.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2009-2024 Josh Close -// 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 -namespace CsvHelper.Configuration; - -/// -/// Configuration used for the . -/// -public interface IReaderConfiguration : IParserConfiguration -{ - /// - /// Gets a value indicating if the - /// CSV file has a header record. - /// Default is true. - /// - bool HasHeaderRecord { get; } - - /// - /// Gets the function that is called when a header validation check is ran. The default function - /// will throw a if there is no header for a given member mapping. - /// You can supply your own function to do other things like logging the issue instead of throwing an exception. - /// - HeaderValidated HeaderValidated { get; } - - /// - /// Gets the function that is called when a missing field is found. The default function will - /// throw a . You can supply your own function to do other things - /// like logging the issue instead of throwing an exception. - /// - MissingFieldFound MissingFieldFound { get; } - - /// - /// Gets the function that is called when a reading exception occurs. - /// The default function will re-throw the given exception. If you want to ignore - /// reading exceptions, you can supply your own function to do other things like - /// logging the issue. - /// - ReadingExceptionOccurred ReadingExceptionOccurred { get; } - - /// - /// Prepares the header field for matching against a member name. - /// The header field and the member name are both ran through this function. - /// You should do things like trimming, removing whitespace, removing underscores, - /// and making casing changes to ignore case. - /// - PrepareHeaderForMatch PrepareHeaderForMatch { get; } - - /// - /// Determines if constructor parameters should be used to create - /// the class instead of the default constructor and members. - /// - ShouldUseConstructorParameters ShouldUseConstructorParameters { get; } - - /// - /// Chooses the constructor to use for constructor mapping. - /// - GetConstructor GetConstructor { get; } - - /// - /// Gets the name to use for the property of the dynamic object. - /// - GetDynamicPropertyName GetDynamicPropertyName { get; } - - /// - /// Gets a value indicating whether references - /// should be ignored when auto mapping. true to ignore - /// references, otherwise false. Default is false. - /// - bool IgnoreReferences { get; } - - /// - /// Gets the callback that will be called to - /// determine whether to skip the given record or not. - /// - ShouldSkipRecord? ShouldSkipRecord { get; } - - /// - /// Gets a value indicating if private - /// member should be read from and written to. - /// true to include private member, otherwise false. Default is false. - /// - bool IncludePrivateMembers { get; } - - /// - /// Gets a callback that will return the prefix for a reference header. - /// - ReferenceHeaderPrefix? ReferenceHeaderPrefix { get; } - - /// - /// Gets a value indicating whether changes in the column - /// count should be detected. If true, a - /// will be thrown if a different column count is detected. - /// - bool DetectColumnCountChanges { get; } - - /// - /// Gets the member types that are used when auto mapping. - /// MemberTypes are flags, so you can choose more than one. - /// Default is Properties. - /// - MemberTypes MemberTypes { get; } -} diff --git a/src/CsvHelper/Configuration/IReaderOptions.cs b/src/CsvHelper/Configuration/IReaderOptions.cs new file mode 100644 index 000000000..c81d39432 --- /dev/null +++ b/src/CsvHelper/Configuration/IReaderOptions.cs @@ -0,0 +1,8 @@ +namespace CsvHelper.Configuration; + +/// +/// Options for . +/// +public interface IReaderOptions +{ +} diff --git a/src/CsvHelper/Configuration/IReadingOptions.cs b/src/CsvHelper/Configuration/IReadingOptions.cs new file mode 100644 index 000000000..997e14419 --- /dev/null +++ b/src/CsvHelper/Configuration/IReadingOptions.cs @@ -0,0 +1,8 @@ +namespace CsvHelper.Configuration; + +/// +/// Options for and . +/// +public interface IReadingOptions : IReaderOptions, IParserOptions +{ +} diff --git a/src/CsvHelper/Configuration/ISerializerOptions.cs b/src/CsvHelper/Configuration/ISerializerOptions.cs new file mode 100644 index 000000000..958568b19 --- /dev/null +++ b/src/CsvHelper/Configuration/ISerializerOptions.cs @@ -0,0 +1,8 @@ +namespace CsvHelper.Configuration; + +/// +/// Options for . +/// +public interface ISerializerOptions +{ +} diff --git a/src/CsvHelper/Configuration/IWriterConfiguration.cs b/src/CsvHelper/Configuration/IWriterConfiguration.cs deleted file mode 100644 index 36c36aabd..000000000 --- a/src/CsvHelper/Configuration/IWriterConfiguration.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2009-2024 Josh Close -// 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 System.Globalization; - -namespace CsvHelper.Configuration; - -/// -/// Configuration used for the . -/// -public interface IWriterConfiguration -{ - /// - /// Gets the size of the buffer - /// used for parsing and writing CSV files. - /// Default is 0x1000. - /// - int BufferSize { get; } - - /// - /// The mode. - /// See for more details. - /// - CsvMode Mode { get; } - - /// - /// Gets the delimiter used to separate fields. - /// Default is ','; - /// - string Delimiter { get; } - - /// - /// Gets the character used to quote fields. - /// Default is '"'. - /// - char Quote { get; } - - /// - /// The character used to escape characters. - /// Default is '"'. - /// - char Escape { get; } - - /// - /// Gets the field trimming options. - /// - TrimOptions TrimOptions { get; } - - /// - /// Gets the injection options. - /// - InjectionOptions InjectionOptions { get; } - - /// - /// Gets the characters that are used for injection attacks. - /// - char[] InjectionCharacters { get; } - - /// - /// Gets the character used to escape a detected injection. - /// - char InjectionEscapeCharacter { get; } - - /// - /// The newline string to use. Default is \r\n (CRLF). - /// When writing, this value is always used. - /// When reading, this value is only used if explicitly set. If not set, - /// the parser uses one of \r\n, \r, or \n. - /// - string NewLine { get; } - - /// - /// A value indicating if was set. - /// - /// - /// true if was set. false if is the default. - /// - bool IsNewLineSet { get; } - - /// - /// Gets a function that is used to determine if a field should get quoted - /// when writing. - /// - ShouldQuote ShouldQuote { get; } - - /// - /// Gets the culture info used to read and write CSV files. - /// - CultureInfo CultureInfo { get; } - - /// - /// Gets a value indicating if comments are allowed. - /// True to allow commented out lines, otherwise false. - /// - bool AllowComments { get; } - - /// - /// Gets the character used to denote - /// a line that is commented out. Default is '#'. - /// - char Comment { get; } - - /// - /// Gets a value indicating if the - /// CSV file has a header record. - /// Default is true. - /// - bool HasHeaderRecord { get; } - - /// - /// Gets a value indicating whether references - /// should be ignored when auto mapping. True to ignore - /// references, otherwise false. Default is false. - /// - bool IgnoreReferences { get; } - - /// - /// Gets a value indicating if private - /// member should be read from and written to. - /// True to include private member, otherwise false. Default is false. - /// - bool IncludePrivateMembers { get; } - - /// - /// Gets a callback that will return the prefix for a reference header. - /// - ReferenceHeaderPrefix? ReferenceHeaderPrefix { get; } - - /// - /// Gets the member types that are used when auto mapping. - /// MemberTypes are flags, so you can choose more than one. - /// Default is Properties. - /// - MemberTypes MemberTypes { get; } - - /// - /// Gets a value indicating that during writing if a new - /// object should be created when a reference member is null. - /// True to create a new object and use it's defaults for the - /// fields, or false to leave the fields empty for all the - /// reference member's member. - /// - bool UseNewObjectForNullReferenceMembers { get; } - - /// - /// Gets the comparer used to order the properties - /// of dynamic objects when writing. The default is null, - /// which will preserve the order the object properties - /// were created with. - /// - IComparer? DynamicPropertySort { get; } - - /// - /// A value indicating if exception messages contain raw CSV data. - /// true if exception contain raw CSV data, otherwise false. - /// Default is true. - /// - bool ExceptionMessagesContainRawData { get; } - - /// - /// Validates the configuration. - /// - void Validate(); -} diff --git a/src/CsvHelper/Configuration/IWriterOptions.cs b/src/CsvHelper/Configuration/IWriterOptions.cs new file mode 100644 index 000000000..1735b85b8 --- /dev/null +++ b/src/CsvHelper/Configuration/IWriterOptions.cs @@ -0,0 +1,8 @@ +namespace CsvHelper.Configuration; + +/// +/// Options for . +/// +public interface IWriterOptions +{ +} diff --git a/src/CsvHelper/Configuration/IWritingOptions.cs b/src/CsvHelper/Configuration/IWritingOptions.cs new file mode 100644 index 000000000..f9a45b3cb --- /dev/null +++ b/src/CsvHelper/Configuration/IWritingOptions.cs @@ -0,0 +1,8 @@ +namespace CsvHelper.Configuration; + +/// +/// Options for and . +/// +public interface IWritingOptions : IWriterOptions, ISerializerOptions +{ +} diff --git a/src/CsvHelper/CsvParser.cs b/src/CsvHelper/CsvParser.cs index 677a0d9a4..0df5ff215 100644 --- a/src/CsvHelper/CsvParser.cs +++ b/src/CsvHelper/CsvParser.cs @@ -11,7 +11,7 @@ namespace CsvHelper; public class CsvParser : IParser, IDisposable { private TextReader reader; - private CsvParserOptions options; + private CsvOptions options; private bool isDisposed; private int rowNumber; private bool leaveOpen; @@ -41,54 +41,57 @@ public class CsvParser : IParser, IDisposable /// Initializes a new instance of CsvParser. /// /// The reader. + /// Options for the parser. /// If set to true, leave the reader open when CsvParser is disposed. - public CsvParser(TextReader reader, bool leaveOpen = false) : this(reader, options => options, leaveOpen) { } - - /// - /// Initializes a new instance of CsvParser. - /// - /// The reader. - /// Function to configure the parser. - /// If set to true, leave the reader open when CsvParser is disposed. - public CsvParser(TextReader reader, Func configure, bool leaveOpen = false) + public CsvParser(TextReader reader, CsvOptions? options, bool leaveOpen = false) { this.reader = reader; this.leaveOpen = leaveOpen; + this.options = options ?? new CsvOptions(); - options = configure(new CsvParserOptions()); - options.Validate(); + this.options.Validate(); - detectDelimiter = options.DetectDelimiter; + detectDelimiter = this.options.DetectDelimiter; - switch (options.Mode) + switch (this.options.Mode) { case CsvMode.RFC4180: - options.ModeParse = ModeRfc4180.Parse; + this.options.ModeParse = ModeRfc4180.Parse; break; case CsvMode.Escape: - options.ModeParse = ModeEscape.Parse; + this.options.ModeParse = ModeEscape.Parse; break; case CsvMode.NoEscape: - options.ModeParse = ModeNoEscape.Parse; + this.options.ModeParse = ModeNoEscape.Parse; break; default: - throw new ConfigurationException($"Mode {options.Mode} is not supported."); + throw new ConfigurationException($"Mode {this.options.Mode} is not supported."); } - options.ParsingStrategyImplementation = ParsingStrategyFactory.Create(options); + this.options.ParsingStrategyImplementation = ParsingStrategyFactory.Create(this.options); - if (options.CacheFields) + if (this.options.CacheFields) { var stringCache = new StringCache(); - options = options with + this.options = this.options with { StringCreator = (chars, _) => stringCache.GetString(chars) }; } - state = new CsvParserState(reader, options); + state = new CsvParserState(reader, this.options); } + /// + /// Initializes a new instance of CsvParser. + /// + /// The reader. + /// Action to configure options for the parser. + /// If set to true, leave the reader open when CsvParser is disposed. + public CsvParser(TextReader reader, Action? configure, bool leaveOpen = false) : this(reader, o => { configure?.Invoke(o); return o; }, leaveOpen) { } + + private CsvParser(TextReader reader, Func? configure, bool leaveOpen = false) : this(reader, (CsvOptions?)configure?.Invoke(new CsvOptions()), leaveOpen) { } + /// /// Moves to the next record. /// @@ -108,15 +111,7 @@ public bool MoveNext() return false; } - if (!delimiterDetected) - { - if (detectDelimiter) - { - options.Delimiter = options.GetDelimiter(state.buffer); - } - - delimiterDetected = true; - } + DetectDelimiter(); state.Parse(); state.NextRow(); @@ -243,11 +238,19 @@ protected virtual void Dispose(bool isDisposing) [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DetectDelimiter() { - if (delimiterDetected || ) + if (delimiterDetected) { return; } + delimiterDetected = true; + + if (!detectDelimiter) + { + return; + } + var args = new GetDelimiterArgs(state.buffer.AsSpan(), options); + options.Delimiter = options.GetDelimiter(args); } } diff --git a/src/CsvHelper/CsvParserState.cs b/src/CsvHelper/CsvParserState.cs index 3bdb3fe5e..c8d5005d3 100644 --- a/src/CsvHelper/CsvParserState.cs +++ b/src/CsvHelper/CsvParserState.cs @@ -14,7 +14,7 @@ internal class CsvParserState : IDisposable, IRow internal StringCreator stringCreator; internal bool isDisposed; - internal CsvParserOptions options; + internal CsvOptions options; internal TextReader reader; internal char[] buffer; @@ -44,7 +44,7 @@ internal class CsvParserState : IDisposable, IRow public ReadOnlySpan Row => GetRow(); - public CsvParserState(TextReader reader, CsvParserOptions options) + public CsvParserState(TextReader reader, CsvOptions options) { this.options = options; this.reader = reader; diff --git a/src/CsvHelper/CsvReader.cs b/src/CsvHelper/CsvReader.cs index 29457255b..66b453e9e 100644 --- a/src/CsvHelper/CsvReader.cs +++ b/src/CsvHelper/CsvReader.cs @@ -41,45 +41,39 @@ public class CsvReader : IReader private string[]? headerRecord; /// - public virtual int ColumnCount => parser.Count; + public int ColumnCount => parser.Current.Count; /// - public virtual int CurrentIndex => currentIndex; + public int CurrentIndex => currentIndex; /// - public virtual string[]? HeaderRecord => headerRecord; + public string[]? HeaderRecord => headerRecord; /// - public virtual CsvContext Context => context; + public CsvContext Context => context; /// - public virtual IReaderConfiguration Configuration { get; private set; } + public IReaderConfiguration Configuration { get; private set; } /// - public virtual IParser Parser => parser; + public IParser Parser => parser; /// - /// Creates a new CSV reader using the given . + /// Creates a new CSV reader. /// /// The reader. - /// The culture. + /// A function to configure options for the reader. + /// A function to configure options for the default parser. /// true to leave the open after the object is disposed, otherwise false. - public CsvReader(TextReader reader, CultureInfo culture, bool leaveOpen = false) : this(new CsvParser(reader, leaveOpen)) { } - - /// - /// Creates a new CSV reader using the given and - /// and as the default parser. - /// - /// The reader. - /// The configuration. - /// true to leave the open after the object is disposed, otherwise false. - public CsvReader(TextReader reader, IReaderConfiguration configuration, bool leaveOpen = false) : this(new CsvParser(reader, configuration, leaveOpen)) { } + public CsvReader(TextReader reader, Func? configureReader = null, Func? configureParser = null, bool leaveOpen = false) + : this(new CsvParser(reader, configureParser, leaveOpen), configureReader) { } /// /// Creates a new CSV reader using the given . /// /// The used to parse the CSV file. - public CsvReader(IParser parser) + /// A function to configure options for the reader. + public CsvReader(IParser parser, Func? configureReader = null) { Configuration = parser.Configuration as IReaderConfiguration ?? throw new ConfigurationException($"The {nameof(IParser)} configuration must implement {nameof(IReaderConfiguration)} to be used in {nameof(CsvReader)}."); @@ -101,7 +95,7 @@ public CsvReader(IParser parser) } /// - public virtual bool ReadHeader() + public bool ReadHeader() { if (!hasHeaderRecord) { @@ -118,7 +112,7 @@ public virtual bool ReadHeader() /// Validates the header to be of the given type. /// /// The expected type of the header - public virtual void ValidateHeader() + public void ValidateHeader() { ValidateHeader(typeof(T)); } @@ -127,7 +121,7 @@ public virtual void ValidateHeader() /// Validates the header to be of the given type. /// /// The expected type of the header. - public virtual void ValidateHeader(Type type) + public void ValidateHeader(Type type) { if (hasHeaderRecord == false) { @@ -159,7 +153,7 @@ public virtual void ValidateHeader(Type type) /// /// The mapped classes. /// The invalid headers. - protected virtual void ValidateHeader(ClassMap map, List invalidHeaders) + protected void ValidateHeader(ClassMap map, List invalidHeaders) { foreach (var parameter in map.ParameterMaps) { @@ -238,7 +232,7 @@ protected virtual void ValidateHeader(ClassMap map, List invalidH } /// - public virtual bool Read() + public bool Read() { // Don't forget about the async method below! @@ -272,7 +266,7 @@ public virtual bool Read() } /// - public virtual async Task ReadAsync() + public async Task ReadAsync() { bool hasMoreRecords; do @@ -304,7 +298,7 @@ public virtual async Task ReadAsync() } /// - public virtual string? this[int index] + public string? this[int index] { get { @@ -315,7 +309,7 @@ public virtual string? this[int index] } /// - public virtual string? this[string name] + public string? this[string name] { get { @@ -326,7 +320,7 @@ public virtual string? this[string name] } /// - public virtual string? this[string name, int index] + public string? this[string name, int index] { get { @@ -337,7 +331,7 @@ public virtual string? this[string name] } /// - public virtual string? GetField(int index) + public string? GetField(int index) { CheckHasBeenRead(); @@ -359,7 +353,7 @@ public virtual string? this[string name] } /// - public virtual string? GetField(string name) + public string? GetField(string name) { CheckHasBeenRead(); @@ -373,7 +367,7 @@ public virtual string? this[string name] } /// - public virtual string? GetField(string name, int index) + public string? GetField(string name, int index) { CheckHasBeenRead(); @@ -387,7 +381,7 @@ public virtual string? this[string name] } /// - public virtual object? GetField(Type type, int index) + public object? GetField(Type type, int index) { CheckHasBeenRead(); @@ -396,7 +390,7 @@ public virtual string? this[string name] } /// - public virtual object? GetField(Type type, string name) + public object? GetField(Type type, string name) { CheckHasBeenRead(); @@ -405,7 +399,7 @@ public virtual string? this[string name] } /// - public virtual object? GetField(Type type, string name, int index) + public object? GetField(Type type, string name, int index) { CheckHasBeenRead(); @@ -414,7 +408,7 @@ public virtual string? this[string name] } /// - public virtual object? GetField(Type type, int index, ITypeConverter converter) + public object? GetField(Type type, int index, ITypeConverter converter) { CheckHasBeenRead(); @@ -433,7 +427,7 @@ public virtual string? this[string name] } /// - public virtual object? GetField(Type type, string name, ITypeConverter converter) + public object? GetField(Type type, string name, ITypeConverter converter) { CheckHasBeenRead(); @@ -442,7 +436,7 @@ public virtual string? this[string name] } /// - public virtual object? GetField(Type type, string name, int index, ITypeConverter converter) + public object? GetField(Type type, string name, int index, ITypeConverter converter) { CheckHasBeenRead(); @@ -451,7 +445,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(int index) + public T? GetField(int index) { CheckHasBeenRead(); @@ -460,7 +454,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(string name) + public T? GetField(string name) { CheckHasBeenRead(); @@ -469,7 +463,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(string name, int index) + public T? GetField(string name, int index) { CheckHasBeenRead(); @@ -478,7 +472,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(int index, ITypeConverter converter) + public T? GetField(int index, ITypeConverter converter) { CheckHasBeenRead(); @@ -495,7 +489,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(string name, ITypeConverter converter) + public T? GetField(string name, ITypeConverter converter) { CheckHasBeenRead(); @@ -504,7 +498,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(string name, int index, ITypeConverter converter) + public T? GetField(string name, int index, ITypeConverter converter) { CheckHasBeenRead(); @@ -513,7 +507,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(int index) where TConverter : ITypeConverter + public T? GetField(int index) where TConverter : ITypeConverter { CheckHasBeenRead(); @@ -522,7 +516,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(string name) where TConverter : ITypeConverter + public T? GetField(string name) where TConverter : ITypeConverter { CheckHasBeenRead(); @@ -531,7 +525,7 @@ public virtual string? this[string name] } /// - public virtual T? GetField(string name, int index) where TConverter : ITypeConverter + public T? GetField(string name, int index) where TConverter : ITypeConverter { CheckHasBeenRead(); @@ -540,7 +534,7 @@ public virtual string? this[string name] } /// - public virtual bool TryGetField(Type type, int index, out object? field) + public bool TryGetField(Type type, int index, out object? field) { CheckHasBeenRead(); @@ -549,7 +543,7 @@ public virtual bool TryGetField(Type type, int index, out object? field) } /// - public virtual bool TryGetField(Type type, string name, out object? field) + public bool TryGetField(Type type, string name, out object? field) { CheckHasBeenRead(); @@ -558,7 +552,7 @@ public virtual bool TryGetField(Type type, string name, out object? field) } /// - public virtual bool TryGetField(Type type, string name, int index, out object? field) + public bool TryGetField(Type type, string name, int index, out object? field) { CheckHasBeenRead(); @@ -567,7 +561,7 @@ public virtual bool TryGetField(Type type, string name, int index, out object? f } /// - public virtual bool TryGetField(Type type, int index, ITypeConverter converter, out object? field) + public bool TryGetField(Type type, int index, ITypeConverter converter, out object? field) { CheckHasBeenRead(); @@ -587,7 +581,7 @@ public virtual bool TryGetField(Type type, int index, ITypeConverter converter, } /// - public virtual bool TryGetField(Type type, string name, ITypeConverter converter, out object? field) + public bool TryGetField(Type type, string name, ITypeConverter converter, out object? field) { CheckHasBeenRead(); @@ -602,7 +596,7 @@ public virtual bool TryGetField(Type type, string name, ITypeConverter converter } /// - public virtual bool TryGetField(Type type, string name, int index, ITypeConverter converter, out object? field) + public bool TryGetField(Type type, string name, int index, ITypeConverter converter, out object? field) { CheckHasBeenRead(); @@ -617,7 +611,7 @@ public virtual bool TryGetField(Type type, string name, int index, ITypeConverte } /// - public virtual bool TryGetField(int index, out T? field) + public bool TryGetField(int index, out T? field) { CheckHasBeenRead(); @@ -626,7 +620,7 @@ public virtual bool TryGetField(int index, out T? field) } /// - public virtual bool TryGetField(string name, out T? field) + public bool TryGetField(string name, out T? field) { CheckHasBeenRead(); @@ -635,7 +629,7 @@ public virtual bool TryGetField(string name, out T? field) } /// - public virtual bool TryGetField(string name, int index, out T? field) + public bool TryGetField(string name, int index, out T? field) { CheckHasBeenRead(); @@ -644,7 +638,7 @@ public virtual bool TryGetField(string name, int index, out T? field) } /// - public virtual bool TryGetField(int index, ITypeConverter converter, out T? field) + public bool TryGetField(int index, ITypeConverter converter, out T? field) { CheckHasBeenRead(); @@ -664,7 +658,7 @@ public virtual bool TryGetField(int index, ITypeConverter converter, out T? f } /// - public virtual bool TryGetField(string name, ITypeConverter converter, out T? field) + public bool TryGetField(string name, ITypeConverter converter, out T? field) { CheckHasBeenRead(); @@ -679,7 +673,7 @@ public virtual bool TryGetField(string name, ITypeConverter converter, out T? } /// - public virtual bool TryGetField(string name, int index, ITypeConverter converter, out T? field) + public bool TryGetField(string name, int index, ITypeConverter converter, out T? field) { CheckHasBeenRead(); @@ -694,7 +688,7 @@ public virtual bool TryGetField(string name, int index, ITypeConverter conver } /// - public virtual bool TryGetField(int index, out T? field) where TConverter : ITypeConverter + public bool TryGetField(int index, out T? field) where TConverter : ITypeConverter { CheckHasBeenRead(); @@ -703,7 +697,7 @@ public virtual bool TryGetField(int index, out T? field) where TC } /// - public virtual bool TryGetField(string name, out T? field) where TConverter : ITypeConverter + public bool TryGetField(string name, out T? field) where TConverter : ITypeConverter { CheckHasBeenRead(); @@ -712,7 +706,7 @@ public virtual bool TryGetField(string name, out T? field) where } /// - public virtual bool TryGetField(string name, int index, out T? field) where TConverter : ITypeConverter + public bool TryGetField(string name, int index, out T? field) where TConverter : ITypeConverter { CheckHasBeenRead(); @@ -721,7 +715,7 @@ public virtual bool TryGetField(string name, int index, out T? fi } /// - public virtual T? GetRecord() + public T? GetRecord() { CheckHasBeenRead(); @@ -766,7 +760,7 @@ record = default; } /// - public virtual T? GetRecord(T anonymousTypeDefinition) + public T? GetRecord(T anonymousTypeDefinition) { if (anonymousTypeDefinition == null) { @@ -782,7 +776,7 @@ record = default; } /// - public virtual object? GetRecord(Type type) + public object? GetRecord(Type type) { CheckHasBeenRead(); @@ -827,7 +821,7 @@ record = default; } /// - public virtual IEnumerable GetRecords() + public IEnumerable GetRecords() { if (disposed) { @@ -892,7 +886,7 @@ record = read(); } /// - public virtual IEnumerable GetRecords(T anonymousTypeDefinition) + public IEnumerable GetRecords(T anonymousTypeDefinition) { if (anonymousTypeDefinition == null) { @@ -908,7 +902,7 @@ public virtual IEnumerable GetRecords(T anonymousTypeDefinition) } /// - public virtual IEnumerable GetRecords(Type type) + public IEnumerable GetRecords(Type type) { if (disposed) { @@ -973,7 +967,7 @@ record = read(); } /// - public virtual IEnumerable EnumerateRecords(T record) + public IEnumerable EnumerateRecords(T record) { if (disposed) { @@ -1030,7 +1024,7 @@ public virtual IEnumerable EnumerateRecords(T record) } /// - public virtual async IAsyncEnumerable GetRecordsAsync([EnumeratorCancellation] CancellationToken cancellationToken = default(CancellationToken)) + public async IAsyncEnumerable GetRecordsAsync([EnumeratorCancellation] CancellationToken cancellationToken = default(CancellationToken)) { if (disposed) { @@ -1096,7 +1090,7 @@ record = read(); } /// - public virtual IAsyncEnumerable GetRecordsAsync(T anonymousTypeDefinition, CancellationToken cancellationToken = default) + public IAsyncEnumerable GetRecordsAsync(T anonymousTypeDefinition, CancellationToken cancellationToken = default) { if (anonymousTypeDefinition == null) { @@ -1112,7 +1106,7 @@ public virtual IAsyncEnumerable GetRecordsAsync(T anonymousTypeDefinition, } /// - public virtual async IAsyncEnumerable GetRecordsAsync(Type type, [EnumeratorCancellation] CancellationToken cancellationToken = default) + public async IAsyncEnumerable GetRecordsAsync(Type type, [EnumeratorCancellation] CancellationToken cancellationToken = default) { if (disposed) { @@ -1178,7 +1172,7 @@ record = read(); } /// - public virtual async IAsyncEnumerable EnumerateRecordsAsync(T record, [EnumeratorCancellation] CancellationToken cancellationToken = default) + public async IAsyncEnumerable EnumerateRecordsAsync(T record, [EnumeratorCancellation] CancellationToken cancellationToken = default) { if (disposed) { @@ -1242,7 +1236,7 @@ public virtual async IAsyncEnumerable EnumerateRecordsAsync(T record, [Enu /// The index of the field. /// Indicates if a TryGet is executed. /// The index of the field. - public virtual int GetFieldIndex(string name, int index = 0, bool isTryGet = false) + public int GetFieldIndex(string name, int index = 0, bool isTryGet = false) { return GetFieldIndex(new[] { name }, index, isTryGet); } @@ -1255,7 +1249,7 @@ public virtual int GetFieldIndex(string name, int index = 0, bool isTryGet = fal /// Indicates if a TryGet is executed. /// Indicates if the field is optional. /// The index of the field. - public virtual int GetFieldIndex(IEnumerable names, int index = 0, bool isTryGet = false, bool isOptional = false) + public int GetFieldIndex(IEnumerable names, int index = 0, bool isTryGet = false, bool isOptional = false) { if (names == null) { @@ -1320,7 +1314,7 @@ public virtual int GetFieldIndex(IEnumerable names, int index = 0, bool /// /// The member map. /// True if values can be read. - public virtual bool CanRead(MemberMap memberMap) + public bool CanRead(MemberMap memberMap) { var cantRead = // Ignored member; @@ -1345,7 +1339,7 @@ public virtual bool CanRead(MemberMap memberMap) /// /// The member reference map. /// True if values can be read. - public virtual bool CanRead(MemberReferenceMap memberReferenceMap) + public bool CanRead(MemberReferenceMap memberReferenceMap) { var cantRead = false; @@ -1374,7 +1368,7 @@ public void Dispose() /// Disposes the object. /// /// Indicates if the object is being disposed. - protected virtual void Dispose(bool disposing) + protected void Dispose(bool disposing) { if (disposed) { @@ -1398,7 +1392,7 @@ protected virtual void Dispose(bool disposing) /// /// Thrown when the file has not yet been read. [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual void CheckHasBeenRead() + protected void CheckHasBeenRead() { if (!hasBeenRead) { @@ -1411,7 +1405,7 @@ protected virtual void CheckHasBeenRead() /// /// Thrown when no header record was found. [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual void ParseNamedIndexes() + protected void ParseNamedIndexes() { if (headerRecord == null) { diff --git a/src/CsvHelper/Delegates/GetDelimiter.cs b/src/CsvHelper/Delegates/GetDelimiter.cs index de00f3886..5ac372056 100644 --- a/src/CsvHelper/Delegates/GetDelimiter.cs +++ b/src/CsvHelper/Delegates/GetDelimiter.cs @@ -26,14 +26,14 @@ public readonly ref struct GetDelimiterArgs /// /// The configuration. /// - public readonly IParserConfiguration Configuration; + public readonly CsvParserOptions Configuration; /// /// Creates an instance of GetDelimiterArgs. /// /// The text to resolve the delimiter from. /// The configuration. - public GetDelimiterArgs(ReadOnlySpan text, IParserConfiguration configuration) + public GetDelimiterArgs(ReadOnlySpan text, CsvParserOptions configuration) { Text = text; Configuration = configuration; diff --git a/src/CsvHelper/IParser.cs b/src/CsvHelper/IParser.cs index 5ca3fc5dc..80fbaacf8 100644 --- a/src/CsvHelper/IParser.cs +++ b/src/CsvHelper/IParser.cs @@ -2,6 +2,8 @@ // 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; + namespace CsvHelper; /// diff --git a/src/CsvHelper/ParsingStrategies/ParsingStrategyFactory.cs b/src/CsvHelper/ParsingStrategies/ParsingStrategyFactory.cs index 9347e62ec..fdff6f8d1 100644 --- a/src/CsvHelper/ParsingStrategies/ParsingStrategyFactory.cs +++ b/src/CsvHelper/ParsingStrategies/ParsingStrategyFactory.cs @@ -10,7 +10,7 @@ namespace CsvHelper; internal static class ParsingStrategyFactory { - public static ICsvParsingStrategy Create(CsvParserOptions options) + public static ICsvParsingStrategy Create(CsvOptions options) { #if NET6_0_OR_GREATER if (options.ParsingStrategy.HasValue)