summaryrefslogtreecommitdiff
path: root/ThirdParty/CsvHelper-master/src/CsvHelper
diff options
context:
space:
mode:
Diffstat (limited to 'ThirdParty/CsvHelper-master/src/CsvHelper')
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ArrayHelper.cs78
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/BadDataException.cs67
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/AllowCommentsAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanFalseValuesAttribute.cs52
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanTrueValuesAttribute.cs52
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BufferSizeAttribute.cs36
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CacheFieldsAttribute.cs36
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CommentAttribute.cs36
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ConstantAttribute.cs47
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CountBytesAttribute.cs45
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CultureInfoAttribute.cs46
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DateTimeStylesAttribute.cs44
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DefaultAttribute.cs45
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DelimiterAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectColumnCountChangesAttribute.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterValuesAttribute.cs37
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EncodingAttribute.cs36
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EnumIgnoreCaseAttribute.cs41
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EscapeAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ExceptionMessagesContainRawDataAttribute.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/FormatAttribute.cs50
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HasHeaderRecordAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HeaderPrefixAttribute.cs73
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IClassMapper.cs19
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberMapper.cs20
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberReferenceMapper.cs20
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterMapper.cs24
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterReferenceMapper.cs24
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreAttribute.cs41
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBaseAttribute.cs20
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBlankLinesAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreReferencesAttribute.cs41
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IncludePrivateMembersAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IndexAttribute.cs57
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionCharactersAttribute.cs37
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionEscapeCharacterAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionOptionsAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/LineBreakInQuotedFieldIsBadDataAttribute.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MaxFieldSizeAttribute.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MemberTypesAttribute.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ModeAttribute.cs38
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameAttribute.cs77
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameIndexAttribute.cs45
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NewLineAttribute.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NullValuesAttribute.cs52
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NumberStylesAttribute.cs44
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/OptionalAttribute.cs27
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ProcessFieldBufferSizeAttribute.cs36
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/QuoteAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TrimOptionsAttribute.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TypeConverterAttribute.cs57
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/UseNewObjectForNullReferenceMembersAttribute.cs47
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/WhiteSpaceCharsAttribute.cs41
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap.cs648
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapBuilder.cs432
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapCollection.cs188
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap`1.cs112
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationException.cs36
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationFunctions.cs267
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/CsvConfiguration.cs240
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/DefaultClassMap`1.cs15
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IParserConfiguration.cs176
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IReaderConfiguration.cs111
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IWriterConfiguration.cs168
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/InjectionOptions.cs31
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap.cs244
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapCollection.cs247
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapComparer.cs74
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapData.cs167
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapTypeConverterOption.cs167
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap`1.cs270
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberNameCollection.cs98
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMap.cs68
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapCollection.cs164
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapData.cs68
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberTypes.cs32
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMap.cs212
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapData.cs106
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapTypeConverterOption.cs160
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMap.cs66
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMapData.cs70
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/TrimOptions.cs30
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvContext.cs202
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvDataReader.cs387
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.csproj92
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net45.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net47.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net5.0.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net50.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net6.0.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net60.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.0.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.1.v3.ncrunchproject5
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.snkbin0 -> 596 bytes
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelperException.cs144
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvMode.cs43
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvParser.cs1194
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvReader.cs1419
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/CsvWriter.cs842
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/BadDataFound.cs52
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertFromString.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertToString.cs41
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetConstructor.cs38
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDelimiter.cs44
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDynamicPropertyName.cs44
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/HeaderValidated.cs46
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/MissingFieldFound.cs53
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/PrepareHeaderForMatch.cs47
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReadingExceptionOccurred.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReferenceHeaderPrefix.cs44
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldQuote.cs51
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldSkipRecord.cs37
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldUseConstructorParameters.cs38
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/Validate.cs53
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/EnumerableExtensions.cs27
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordCreator.cs61
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordWriter.cs75
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs49
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpressionManager.cs490
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordCreator.cs66
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordWriter.cs124
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordCreator.cs49
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordWriter.cs57
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreator.cs107
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreatorFactory.cs51
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordHydrator.cs126
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordManager.cs80
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriter.cs109
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriterFactory.cs61
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Factory.cs108
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/FieldCache.cs137
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/FieldValidationException.cs55
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/HeaderValidationException.cs55
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/IFactory.cs85
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/IObjectResolver.cs57
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/IParser.cs89
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/IReader.cs126
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/IReaderRow.cs428
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/IWriter.cs86
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/IWriterRow.cs135
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Icon.pngbin0 -> 728 bytes
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/InvalidHeader.cs28
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/LinkedListExtensions.cs29
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/MaxFieldSizeException.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/MissingFieldException.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ObjectCreator.cs218
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ObjectResolver.cs143
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ParserException.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/Properties/AssemblyInfo.cs13
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ReaderException.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionExtensions.cs155
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs204
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ArrayConverter.cs73
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BigIntegerConverter.cs57
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BooleanConverter.cs72
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverter.cs126
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverterOptions.cs44
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteConverter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CharConverter.cs36
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionConverterFactory.cs175
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionGenericConverter.cs64
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateOnlyConverter.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeConverter.cs43
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeOffsetConverter.cs43
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DecimalConverter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DefaultTypeConverter.cs62
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DoubleConverter.cs57
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverter.cs121
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverterFactory.cs35
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumerableConverter.cs48
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/GuidConverter.cs32
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryConverter.cs65
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryGenericConverter.cs46
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableConverter.cs85
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableGenericConverter.cs65
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverter.cs32
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverterFactory.cs33
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int16Converter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int32Converter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int64Converter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverter.cs94
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverterFactory.cs28
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SByteConverter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SingleConverter.cs57
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/StringConverter.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeOnlyConverter.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeSpanConverter.cs41
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverter.cs52
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterCache.cs242
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterException.cs132
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptions.cs157
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptionsCache.cs108
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt16Converter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt32Converter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt64Converter.cs34
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UriConverter.cs40
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ValidationException.cs39
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/WriterException.cs39
199 files changed, 18616 insertions, 0 deletions
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ArrayHelper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ArrayHelper.cs
new file mode 100644
index 0000000..16b15db
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ArrayHelper.cs
@@ -0,0 +1,78 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Methods to help with arrays.
+ /// </summary>
+ public static class ArrayHelper
+ {
+ /// <summary>
+ /// Trims the characters off the start and end of the buffer
+ /// by updating the start and length arguments.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="start">The start.</param>
+ /// <param name="length">The length.</param>
+ /// <param name="trimChars">The characters to trim.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Trim(char[] buffer, ref int start, ref int length, char[] trimChars)
+ {
+ // Trim start.
+ for (var i = start; i < start + length; i++)
+ {
+ var c = buffer[i];
+ if (!Contains(trimChars, c))
+ {
+ break;
+ }
+
+ start++;
+ length--;
+ }
+
+ // Trim end.
+ for (var i = start + length - 1; i > start; i--)
+ {
+ var c = buffer[i];
+ if (!Contains(trimChars, c))
+ {
+ break;
+ }
+
+ length--;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether this given array contains the given character.
+ /// </summary>
+ /// <param name="array">The array to search.</param>
+ /// <param name="c">The character to look for.</param>
+ /// <returns>
+ /// <c>true</c> if the array contains the characters, otherwise <c>false</c>.
+ /// </returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Contains(char[] array, in char c)
+ {
+ for (var i = 0; i < array.Length; i++)
+ {
+ if (array[i] == c)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/BadDataException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/BadDataException.cs
new file mode 100644
index 0000000..9aecd38
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/BadDataException.cs
@@ -0,0 +1,67 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents errors that occur due to bad data.
+ /// </summary>
+ [Serializable]
+ public class BadDataException : CsvHelperException
+ {
+ /// <summary>
+ /// The full field unedited.
+ /// </summary>
+ public readonly string Field;
+
+ /// <summary>
+ /// The full row unedited.
+ /// </summary>
+ public readonly string RawRecord;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BadDataException"/> class.
+ /// </summary>
+ /// <param name="field">The full field unedited.</param>
+ /// <param name="rawRecord">The full row unedited.</param>
+ /// <param name="context">The reading context.</param>
+ public BadDataException(string field, string rawRecord, CsvContext context) : base(context)
+ {
+ Field = field;
+ RawRecord = rawRecord;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BadDataException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="field">The full field unedited.</param>
+ /// <param name="rawRecord">The full row unedited.</param>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public BadDataException(string field, string rawRecord, CsvContext context, string message) : base(context, message)
+ {
+ Field = field;
+ RawRecord = rawRecord;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BadDataException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="field">The full field unedited.</param>
+ /// <param name="rawRecord">The full row unedited.</param>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public BadDataException(string field, string rawRecord, CsvContext context, string message, Exception innerException) : base(context, message, innerException)
+ {
+ Field = field;
+ RawRecord = rawRecord;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/AllowCommentsAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/AllowCommentsAttribute.cs
new file mode 100644
index 0000000..1490cc9
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/AllowCommentsAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// A value indicating if comments are allowed.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class AllowCommentsAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets a value indicating if comments are allowed.
+ /// </summary>
+ public bool AllowComments { get; private set; }
+
+ /// <summary>
+ /// A value indicating if comments are allowed.
+ /// </summary>
+ /// <param name="allowComments">The value indicating id comments are allowed.</param>
+ public AllowCommentsAttribute(bool allowComments)
+ {
+ AllowComments = allowComments;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.AllowComments = AllowComments;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanFalseValuesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanFalseValuesAttribute.cs
new file mode 100644
index 0000000..b26315b
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanFalseValuesAttribute.cs
@@ -0,0 +1,52 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The string values used to represent a boolean false when converting.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class BooleanFalseValuesAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the false values.
+ /// </summary>
+ public string[] FalseValues { get; private set; }
+
+ /// <summary>
+ /// The string values used to represent a boolean false when converting.
+ /// </summary>
+ /// <param name="falseValue">The false values.</param>
+ public BooleanFalseValuesAttribute(string falseValue)
+ {
+ FalseValues = new string[] { falseValue };
+ }
+
+ /// <summary>
+ /// The string values used to represent a boolean false when converting.
+ /// </summary>
+ /// <param name="falseValues">The false values.</param>
+ public BooleanFalseValuesAttribute(params string[] falseValues)
+ {
+ FalseValues = falseValues;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.BooleanFalseValues.Clear();
+ memberMap.Data.TypeConverterOptions.BooleanFalseValues.AddRange(FalseValues);
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.BooleanFalseValues.Clear();
+ parameterMap.Data.TypeConverterOptions.BooleanFalseValues.AddRange(FalseValues);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanTrueValuesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanTrueValuesAttribute.cs
new file mode 100644
index 0000000..3a9b591
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanTrueValuesAttribute.cs
@@ -0,0 +1,52 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The string values used to represent a boolean true when converting.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class BooleanTrueValuesAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the true values.
+ /// </summary>
+ public string[] TrueValues { get; private set; }
+
+ /// <summary>
+ /// The string values used to represent a boolean true when converting.
+ /// </summary>
+ /// <param name="trueValue"></param>
+ public BooleanTrueValuesAttribute(string trueValue)
+ {
+ TrueValues = new string[] { trueValue };
+ }
+
+ /// <summary>
+ /// The string values used to represent a boolean true when converting.
+ /// </summary>
+ /// <param name="trueValues"></param>
+ public BooleanTrueValuesAttribute(params string[] trueValues)
+ {
+ TrueValues = trueValues;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.BooleanTrueValues.Clear();
+ memberMap.Data.TypeConverterOptions.BooleanTrueValues.AddRange(TrueValues);
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.BooleanTrueValues.Clear();
+ parameterMap.Data.TypeConverterOptions.BooleanTrueValues.AddRange(TrueValues);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BufferSizeAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BufferSizeAttribute.cs
new file mode 100644
index 0000000..f74e98e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BufferSizeAttribute.cs
@@ -0,0 +1,36 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The size of the buffer used for parsing and writing CSV files.
+ /// Default is 0x1000.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class BufferSizeAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// The buffer size.
+ /// </summary>
+ public int BufferSize { get; private set; }
+
+ /// <summary>
+ /// The size of the buffer used for parsing and writing CSV files.
+ /// </summary>
+ /// <param name="bufferSize"></param>
+ public BufferSizeAttribute(int bufferSize)
+ {
+ BufferSize = bufferSize;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.BufferSize = BufferSize;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CacheFieldsAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CacheFieldsAttribute.cs
new file mode 100644
index 0000000..1f6b859
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CacheFieldsAttribute.cs
@@ -0,0 +1,36 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Cache fields that are created when parsing.
+ /// Default is false.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class CacheFieldsAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Cache fields that are created when parsing.
+ /// </summary>
+ public bool CacheFields { get; private set; }
+
+ /// <summary>
+ /// Cache fields that are created when parsing.
+ /// </summary>
+ /// <param name="cacheFields"></param>
+ public CacheFieldsAttribute(bool cacheFields)
+ {
+ CacheFields = cacheFields;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.CacheFields = CacheFields;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CommentAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CommentAttribute.cs
new file mode 100644
index 0000000..c0c6124
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CommentAttribute.cs
@@ -0,0 +1,36 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The character used to denote a line that is commented out.
+ /// Default is #.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class CommentAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets the character used to denote a line that is commented out.
+ /// </summary>
+ public char Comment { get; private set; }
+
+ /// <summary>
+ /// The character used to denote a line that is commented out.
+ /// </summary>
+ /// <param name="comment">The comment character.</param>
+ public CommentAttribute(char comment)
+ {
+ Comment = comment;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.Comment = Comment;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ConstantAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ConstantAttribute.cs
new file mode 100644
index 0000000..5dd2dc5
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ConstantAttribute.cs
@@ -0,0 +1,47 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The constant value that will be used for every record when
+ /// reading and writing. This value will always be used no matter
+ /// what other mapping configurations are specified.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class ConstantAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the constant.
+ /// </summary>
+ public object Constant { get; private set; }
+
+ /// <summary>
+ /// The constant value that will be used for every record when
+ /// reading and writing. This value will always be used no matter
+ /// what other mapping configurations are specified.
+ /// </summary>
+ /// <param name="constant">The constant.</param>
+ public ConstantAttribute(object constant)
+ {
+ Constant = constant;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.Constant = Constant;
+ memberMap.Data.IsConstantSet = true;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.Constant = Constant;
+ parameterMap.Data.IsConstantSet = true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CountBytesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CountBytesAttribute.cs
new file mode 100644
index 0000000..165784e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CountBytesAttribute.cs
@@ -0,0 +1,45 @@
+// Copyright 2009-2022 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;
+using System.Text;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// 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 <see cref="Encoding"/> needs to be set correctly for this to be accurate.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class CountBytesAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// 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 <see cref="Encoding"/> needs to be set correctly for this to be accurate.
+ /// </summary>
+ public bool CountBytes { get; private set; }
+
+ /// <summary>
+ /// 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 <see cref="Encoding"/> needs to be set correctly for this to be accurate.
+ /// </summary>
+ /// <param name="countBytes"></param>
+ public CountBytesAttribute(bool countBytes)
+ {
+ CountBytes = countBytes;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.CountBytes = CountBytes;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CultureInfoAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CultureInfoAttribute.cs
new file mode 100644
index 0000000..47940fb
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CultureInfoAttribute.cs
@@ -0,0 +1,46 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The <see cref="CultureInfo"/> used when type converting.
+ /// This will override the global <see cref="CsvConfiguration.CultureInfo"/>
+ /// setting. Or set the same if the attribute is specified on class level.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class CultureInfoAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the culture info.
+ /// </summary>
+ public CultureInfo CultureInfo { get; private set; }
+
+ /// <summary>
+ /// The <see cref="CultureInfo"/> used when type converting.
+ /// This will override the global <see cref="CsvConfiguration.CultureInfo"/>
+ /// setting. Or set the same if the attribute is specified on class level.
+ /// </summary>
+ /// <param name="culture">The culture.</param>
+ public CultureInfoAttribute(string culture)
+ {
+ CultureInfo = CultureInfo.GetCultureInfo(culture);
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.CultureInfo = CultureInfo;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.CultureInfo = CultureInfo;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DateTimeStylesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DateTimeStylesAttribute.cs
new file mode 100644
index 0000000..42fd789
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DateTimeStylesAttribute.cs
@@ -0,0 +1,44 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The <see cref="DateTimeStyles"/> to use when type converting.
+ /// This is used when doing any <see cref="DateTime"/> conversions.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class DateTimeStylesAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the date time styles.
+ /// </summary>
+ public DateTimeStyles DateTimeStyles { get; private set; }
+
+ /// <summary>
+ /// The <see cref="DateTimeStyles"/> to use when type converting.
+ /// This is used when doing any <see cref="DateTime"/> conversions.
+ /// </summary>
+ /// <param name="dateTimeStyles">The date time styles.</param>
+ public DateTimeStylesAttribute(DateTimeStyles dateTimeStyles)
+ {
+ DateTimeStyles = dateTimeStyles;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.DateTimeStyle = DateTimeStyles;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.DateTimeStyle = DateTimeStyles;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DefaultAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DefaultAttribute.cs
new file mode 100644
index 0000000..f2e4e46
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DefaultAttribute.cs
@@ -0,0 +1,45 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class DefaultAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the default value.
+ /// </summary>
+ public object Default { get; private set; }
+
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty.
+ /// </summary>
+ /// <param name="defaultValue">The default value</param>
+ public DefaultAttribute(object defaultValue)
+ {
+ Default = defaultValue;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.Default = Default;
+ memberMap.Data.IsDefaultSet = true;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.Default = Default;
+ parameterMap.Data.IsDefaultSet = true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DelimiterAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DelimiterAttribute.cs
new file mode 100644
index 0000000..b8b53f6
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DelimiterAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The delimiter used to separate fields.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class DelimiterAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets the delimiter.
+ /// </summary>
+ public string Delimiter { get; private set; }
+
+ /// <summary>
+ /// The delimiter used to separate fields.
+ /// </summary>
+ /// <param name="delimiter">The delimiter.</param>
+ public DelimiterAttribute(string delimiter)
+ {
+ Delimiter = delimiter;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.Delimiter = Delimiter;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectColumnCountChangesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectColumnCountChangesAttribute.cs
new file mode 100644
index 0000000..f31aaf8
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectColumnCountChangesAttribute.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// A value indicating whether changes in the column
+ /// count should be detected. If true, a <see cref="BadDataException"/>
+ /// will be thrown if a different column count is detected.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class DetectColumnCountChangesAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// A value indicating whether changes in the column
+ /// count should be detected. If true, a <see cref="BadDataException"/>
+ /// will be thrown if a different column count is detected.
+ /// </summary>
+ public bool DetectColumnCountChanges { get; private set; }
+
+ /// <summary>
+ /// A value indicating whether changes in the column
+ /// count should be detected. If true, a <see cref="BadDataException"/>
+ /// will be thrown if a different column count is detected.
+ /// </summary>
+ public DetectColumnCountChangesAttribute(bool detectColumnCountChanges)
+ {
+ DetectColumnCountChanges = detectColumnCountChanges;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.DetectColumnCountChanges = DetectColumnCountChanges;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterAttribute.cs
new file mode 100644
index 0000000..2c7da45
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Detect the delimiter instead of using the delimiter from configuration.
+ /// Default is <c>false</c>.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class DetectDelimiterAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Detect the delimiter instead of using the delimiter from configuration.
+ /// </summary>
+ public bool DetectDelimiter { get; private set; }
+
+ /// <summary>
+ /// Detect the delimiter instead of using the delimiter from configuration.
+ /// </summary>
+ public DetectDelimiterAttribute(bool detectDelimiter)
+ {
+ DetectDelimiter = detectDelimiter;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.DetectDelimiter = DetectDelimiter;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterValuesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterValuesAttribute.cs
new file mode 100644
index 0000000..af641df
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterValuesAttribute.cs
@@ -0,0 +1,37 @@
+// Copyright 2009-2022 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;
+using System.Text.RegularExpressions;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The possible delimiter values used when detecting the delimiter.
+ /// Default is [",", ";", "|", "\t"].
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class DetectDelimiterValuesAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// The possible delimiter values used when detecting the delimiter.
+ /// </summary>
+ public string[] DetectDelimiterValues { get; private set; }
+
+ /// <summary>
+ /// The possible delimiter values used when detecting the delimiter.
+ /// </summary>
+ /// <param name="detectDelimiterValues">Whitespace separated list of values.</param>
+ public DetectDelimiterValuesAttribute(string detectDelimiterValues)
+ {
+ DetectDelimiterValues = Regex.Split(detectDelimiterValues, @"\s+");
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.DetectDelimiterValues = DetectDelimiterValues;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EncodingAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EncodingAttribute.cs
new file mode 100644
index 0000000..ee378ba
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EncodingAttribute.cs
@@ -0,0 +1,36 @@
+// Copyright 2009-2022 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;
+using System.Text;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The encoding used when counting bytes.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class EncodingAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets the encoding used when counting bytes.
+ /// </summary>
+ public Encoding Encoding { get; private set; }
+
+ /// <summary>
+ /// The encoding used when counting bytes.
+ /// </summary>
+ /// <param name="encoding">The encoding.</param>
+ public EncodingAttribute(string encoding)
+ {
+ Encoding = Encoding.GetEncoding(encoding);
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.Encoding = Encoding;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EnumIgnoreCaseAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EnumIgnoreCaseAttribute.cs
new file mode 100644
index 0000000..c2b25c9
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EnumIgnoreCaseAttribute.cs
@@ -0,0 +1,41 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Ignore case when parsing enums.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class EnumIgnoreCaseAttribute : Attribute, IMemberMapper, IMemberReferenceMapper, IParameterMapper
+ {
+ /// <inheritdoc/>
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.EnumIgnoreCase = true;
+ }
+
+ /// <inheritdoc/>
+ public void ApplyTo(MemberReferenceMap referenceMap)
+ {
+ foreach (var memberMap in referenceMap.Data.Mapping.MemberMaps)
+ {
+ ApplyTo(memberMap);
+ }
+ }
+
+ /// <inheritdoc/>
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.EnumIgnoreCase = true;
+ }
+
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EscapeAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EscapeAttribute.cs
new file mode 100644
index 0000000..0d20d50
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EscapeAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The escape character used to escape a quote inside a field.
+ /// </summary>
+ [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
+ public class EscapeAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets the escape character used to escape a quote inside a field.
+ /// </summary>
+ public char Escape { get; private set; }
+
+ /// <summary>
+ /// The escape character used to escape a quote inside a field.
+ /// </summary>
+ /// <param name="escape">The escape character.</param>
+ public EscapeAttribute( char escape )
+ {
+ Escape = escape;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.Escape = Escape;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ExceptionMessagesContainRawDataAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ExceptionMessagesContainRawDataAttribute.cs
new file mode 100644
index 0000000..2cb9608
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ExceptionMessagesContainRawDataAttribute.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// A value indicating if exception messages contain raw CSV data.
+ /// <c>true</c> if exception contain raw CSV data, otherwise <c>false</c>.
+ /// Default is <c>true</c>.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class ExceptionMessagesContainRawDataAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// A value indicating if exception messages contain raw CSV data.
+ /// <c>true</c> if exception contain raw CSV data, otherwise <c>false</c>.
+ /// </summary>
+ public bool ExceptionMessagesContainRawData { get; private set; }
+
+ /// <summary>
+ /// A value indicating if exception messages contain raw CSV data.
+ /// <c>true</c> if exception contain raw CSV data, otherwise <c>false</c>.
+ /// </summary>
+ /// <param name="exceptionMessagesContainRawData"></param>
+ public ExceptionMessagesContainRawDataAttribute(bool exceptionMessagesContainRawData)
+ {
+ ExceptionMessagesContainRawData = exceptionMessagesContainRawData;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.ExceptionMessagesContainRawData = ExceptionMessagesContainRawData;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/FormatAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/FormatAttribute.cs
new file mode 100644
index 0000000..b42d8ed
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/FormatAttribute.cs
@@ -0,0 +1,50 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The string format to be used when type converting.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class FormatAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the formats.
+ /// </summary>
+ public string[] Formats { get; private set; }
+
+ /// <summary>
+ /// The string format to be used when type converting.
+ /// </summary>
+ /// <param name="format">The format.</param>
+ public FormatAttribute(string format)
+ {
+ Formats = new string[] { format };
+ }
+
+ /// <summary>
+ /// The string format to be used when type converting.
+ /// </summary>
+ /// <param name="formats">The formats.</param>
+ public FormatAttribute(params string[] formats)
+ {
+ Formats = formats;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.Formats = Formats;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.Formats = Formats;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HasHeaderRecordAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HasHeaderRecordAttribute.cs
new file mode 100644
index 0000000..b0d93ae
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HasHeaderRecordAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// A value indicating if the CSV file has a header record.
+ /// </summary>
+ [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
+ public class HasHeaderRecordAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets a value indicating if the CSV file has a header record.
+ /// </summary>
+ public bool HasHeaderRecord { get; private set; }
+
+ /// <summary>
+ /// A value indicating if the CSV file has a header record.
+ /// </summary>
+ /// <param name="hasHeaderRecord">A value indicating if the CSV file has a header record.</param>
+ public HasHeaderRecordAttribute( bool hasHeaderRecord )
+ {
+ HasHeaderRecord = hasHeaderRecord;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.HasHeaderRecord = HasHeaderRecord;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HeaderPrefixAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HeaderPrefixAttribute.cs
new file mode 100644
index 0000000..4ae8227
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HeaderPrefixAttribute.cs
@@ -0,0 +1,73 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Appends a prefix to the header of each field of the reference member.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class HeaderPrefixAttribute : Attribute, IMemberReferenceMapper, IParameterReferenceMapper
+ {
+ /// <summary>
+ /// Gets the prefix.
+ /// </summary>
+ public string? Prefix { get; private set; }
+
+ /// <summary>
+ /// Gets a value indicating if the prefix should inherit parent prefixes.
+ /// </summary>
+ public bool Inherit { get; private set; }
+
+ /// <summary>
+ /// Appends a prefix to the header of each field of the reference member.
+ /// </summary>
+ public HeaderPrefixAttribute() { }
+
+ /// <summary>
+ /// Appends a prefix to the header of each field of the reference member.
+ /// </summary>
+ /// <param name="prefix">The prefix.</param>
+ public HeaderPrefixAttribute(string prefix)
+ {
+ Prefix = prefix;
+ }
+
+ /// <summary>
+ /// Appends a prefix to the header of each field of the reference member.
+ /// </summary>
+ /// <param name="inherit">Inherits parent object prefixes.</param>
+ public HeaderPrefixAttribute(bool inherit)
+ {
+ Inherit = inherit;
+ }
+
+ /// <summary>
+ /// Appends a prefix to the header of each field of the reference member.
+ /// </summary>
+ /// <param name="prefix">The prefix.</param>
+ /// <param name="inherit">Inherits parent object prefixes.</param>
+ public HeaderPrefixAttribute(string prefix, bool inherit)
+ {
+ Prefix = prefix;
+ Inherit = inherit;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberReferenceMap referenceMap)
+ {
+ referenceMap.Data.Inherit = Inherit;
+ referenceMap.Data.Prefix = Prefix ?? referenceMap.Data.Member.Name + ".";
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterReferenceMap referenceMap)
+ {
+ referenceMap.Data.Inherit = Inherit;
+ referenceMap.Data.Prefix = Prefix ?? referenceMap.Data.Parameter.Name + ".";
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IClassMapper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IClassMapper.cs
new file mode 100644
index 0000000..d395ac9
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IClassMapper.cs
@@ -0,0 +1,19 @@
+// Copyright 2009-2022 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.Attributes
+{
+ /// <summary>
+ /// Defines methods to enable pluggable configuration.
+ /// </summary>
+ public interface IClassMapper
+ {
+ /// <summary>
+ /// Applies configuration.
+ /// </summary>
+ /// <param name="configuration">The configuration to apply to.</param>
+ void ApplyTo(CsvConfiguration configuration);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberMapper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberMapper.cs
new file mode 100644
index 0000000..b8701f1
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberMapper.cs
@@ -0,0 +1,20 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Defines methods to enable pluggable configuration of member mapping.
+ /// </summary>
+ public interface IMemberMapper
+ {
+ /// <summary>
+ /// Applies configuration to the given <see cref="MemberMap"/>.
+ /// </summary>
+ /// <param name="memberMap">The member map.</param>
+ void ApplyTo(MemberMap memberMap);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberReferenceMapper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberReferenceMapper.cs
new file mode 100644
index 0000000..c9c4d32
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberReferenceMapper.cs
@@ -0,0 +1,20 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Defines methods to enable pluggable configuration of member reference mapping.
+ /// </summary>
+ public interface IMemberReferenceMapper
+ {
+ /// <summary>
+ /// Applies configuration to the given <see cref="MemberReferenceMap" />.
+ /// </summary>
+ /// <param name="referenceMap">The reference map.</param>
+ void ApplyTo(MemberReferenceMap referenceMap);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterMapper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterMapper.cs
new file mode 100644
index 0000000..0b5c289
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterMapper.cs
@@ -0,0 +1,24 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Defines methods to enable pluggable configuration of parameter mapping.
+ /// </summary>
+ public interface IParameterMapper
+ {
+ /// <summary>
+ /// Applies configuration to the given <see cref="ParameterMap"/>.
+ /// </summary>
+ /// <param name="parameterMap">The parameter map.</param>
+ void ApplyTo(ParameterMap parameterMap);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterReferenceMapper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterReferenceMapper.cs
new file mode 100644
index 0000000..ea4fc50
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterReferenceMapper.cs
@@ -0,0 +1,24 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Defines methods to enable pluggable configuration of parameter reference mapping.
+ /// </summary>
+ public interface IParameterReferenceMapper
+ {
+ /// <summary>
+ /// Applies configuration to the given <see cref="ParameterReferenceMap" />.
+ /// </summary>
+ /// <param name="referenceMap">The reference map.</param>
+ void ApplyTo(ParameterReferenceMap referenceMap);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreAttribute.cs
new file mode 100644
index 0000000..41a199a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreAttribute.cs
@@ -0,0 +1,41 @@
+// Copyright 2009-2022 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;
+using System.Reflection;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Ignore the member when reading and writing.
+ /// If this member has already been mapped as a reference
+ /// member, either by a class map, or by automapping, calling
+ /// this method will not ignore all the child members down the
+ /// tree that have already been mapped.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class IgnoreAttribute : Attribute, IMemberMapper, IMemberReferenceMapper, IParameterMapper
+ {
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.Ignore = true;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberReferenceMap referenceMap)
+ {
+ foreach (var memberMap in referenceMap.Data.Mapping.MemberMaps)
+ {
+ ApplyTo(memberMap);
+ }
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.Ignore = true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBaseAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBaseAttribute.cs
new file mode 100644
index 0000000..066be2e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBaseAttribute.cs
@@ -0,0 +1,20 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Ignores base classes when auto mapping.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class IgnoreBaseAttribute : Attribute
+ {
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBlankLinesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBlankLinesAttribute.cs
new file mode 100644
index 0000000..c270568
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBlankLinesAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// A value indicating if blank lines should be ignored when reading.
+ /// </summary>
+ [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
+ public class IgnoreBlankLinesAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets a value indicating if blank lines should be ignored when reading.
+ /// </summary>
+ public bool IgnoreBlankLines { get; private set; }
+
+ /// <summary>
+ /// A value indicating if blank lines should be ignored when reading.
+ /// </summary>
+ /// <param name="ignoreBlankLines">The Ignore Blank Lines Flag.</param>
+ public IgnoreBlankLinesAttribute( bool ignoreBlankLines )
+ {
+ IgnoreBlankLines = ignoreBlankLines;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.IgnoreBlankLines = IgnoreBlankLines;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreReferencesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreReferencesAttribute.cs
new file mode 100644
index 0000000..05e7b0e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreReferencesAttribute.cs
@@ -0,0 +1,41 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Gets a value indicating whether references
+ /// should be ignored when auto mapping. <c>true</c> to ignore
+ /// references, otherwise <c>false</c>. Default is false.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class IgnoreReferencesAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets a value indicating whether references
+ /// should be ignored when auto mapping. <c>true</c> to ignore
+ /// references, otherwise <c>false</c>. Default is false.
+ /// </summary>
+ public bool IgnoreReferences { get; private set; }
+
+ /// <summary>
+ /// Gets a value indicating whether references
+ /// should be ignored when auto mapping. <c>true</c> to ignore
+ /// references, otherwise <c>false</c>. Default is false.
+ /// </summary>
+ /// <param name="ignoreReferences">Ignore references value.</param>
+ public IgnoreReferencesAttribute(bool ignoreReferences)
+ {
+ IgnoreReferences = ignoreReferences;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.IgnoreReferences = IgnoreReferences;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IncludePrivateMembersAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IncludePrivateMembersAttribute.cs
new file mode 100644
index 0000000..92c7c1b
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IncludePrivateMembersAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// A value indicating if private member should be read from and written to.
+ /// </summary>
+ [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
+ public class IncludePrivateMembersAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets a value indicating if private member should be read from and written to.
+ /// </summary>
+ public bool IncludePrivateMembers { get; private set; }
+
+ /// <summary>
+ /// A value indicating if private member should be read from and written to.
+ /// </summary>
+ /// <param name="includePrivateMembers">The Include Private Members Flag.</param>
+ public IncludePrivateMembersAttribute( bool includePrivateMembers )
+ {
+ IncludePrivateMembers = includePrivateMembers;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.IncludePrivateMembers = IncludePrivateMembers;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IndexAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IndexAttribute.cs
new file mode 100644
index 0000000..e469741
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IndexAttribute.cs
@@ -0,0 +1,57 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// When reading, is used to get the field at
+ /// the given index. When writing, the fields
+ /// will be written in the order of the field
+ /// indexes.
+ /// </summary>
+ [AttributeUsage( AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true )]
+ public class IndexAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the index.
+ /// </summary>
+ public int Index { get; private set; }
+
+ /// <summary>
+ /// Gets the index end.
+ /// </summary>
+ public int IndexEnd { get; private set; }
+
+ /// <summary>
+ /// When reading, is used to get the field at
+ /// the given index. When writing, the fields
+ /// will be written in the order of the field
+ /// indexes.
+ /// </summary>
+ /// <param name="index">The index.</param>
+ /// <param name="indexEnd">The index end.</param>
+ public IndexAttribute( int index, int indexEnd = -1 )
+ {
+ Index = index;
+ IndexEnd = indexEnd;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.Index = Index;
+ memberMap.Data.IndexEnd = IndexEnd;
+ memberMap.Data.IsIndexSet = true;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.Index = Index;
+ parameterMap.Data.IsIndexSet = true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionCharactersAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionCharactersAttribute.cs
new file mode 100644
index 0000000..66f6964
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionCharactersAttribute.cs
@@ -0,0 +1,37 @@
+// Copyright 2009-2022 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;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Gets the characters that are used for injection attacks.
+ /// </summary>
+ public class InjectionCharactersAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets the characters that are used for injection attacks.
+ /// Default is '=', '@', '+', '-', '\t', '\r'.
+ /// </summary>
+ public char[] InjectionCharacters { get; private set; }
+
+ /// <summary>
+ /// Gets the characters that are used for injection attacks.
+ /// </summary>
+ /// <param name="injectionCharacters"></param>
+ public InjectionCharactersAttribute(string injectionCharacters)
+ {
+ InjectionCharacters = Regex.Split(injectionCharacters, @"\s+").Select(s => s[0]).ToArray();
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.InjectionCharacters = InjectionCharacters;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionEscapeCharacterAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionEscapeCharacterAttribute.cs
new file mode 100644
index 0000000..1db163d
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionEscapeCharacterAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The character used to escape a detected injection.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class InjectionEscapeCharacterAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// The character used to escape a detected injection.
+ /// </summary>
+ public char InjectionEscapeCharacter { get; private set; }
+
+ /// <summary>
+ /// The character used to escape a detected injection.
+ /// </summary>
+ /// <param name="injectionEscapeCharacter"></param>
+ public InjectionEscapeCharacterAttribute(char injectionEscapeCharacter)
+ {
+ InjectionEscapeCharacter = injectionEscapeCharacter;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.InjectionEscapeCharacter = InjectionEscapeCharacter;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionOptionsAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionOptionsAttribute.cs
new file mode 100644
index 0000000..db97300
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionOptionsAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The injection options.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class InjectionOptionsAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// The injection options.
+ /// </summary>
+ public InjectionOptions InjectionOptions { get; private set; }
+
+ /// <summary>
+ /// The injection options.
+ /// </summary>
+ /// <param name="injectionOptions"></param>
+ public InjectionOptionsAttribute(InjectionOptions injectionOptions)
+ {
+ InjectionOptions = injectionOptions;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.InjectionOptions = InjectionOptions;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/LineBreakInQuotedFieldIsBadDataAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/LineBreakInQuotedFieldIsBadDataAttribute.cs
new file mode 100644
index 0000000..db95cbc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/LineBreakInQuotedFieldIsBadDataAttribute.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// A value indicating if a line break found in a quote field should
+ /// be considered bad data. <c>true</c> to consider a line break bad data, otherwise <c>false</c>.
+ /// Defaults to false.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class LineBreakInQuotedFieldIsBadDataAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// A value indicating if a line break found in a quote field should
+ /// be considered bad data. <c>true</c> to consider a line break bad data, otherwise <c>false</c>.
+ /// </summary>
+ public bool LineBreakInQuotedFieldIsBadData { get; private set; }
+
+ /// <summary>
+ /// A value indicating if a line break found in a quote field should
+ /// be considered bad data. <c>true</c> to consider a line break bad data, otherwise <c>false</c>.
+ /// </summary>
+ /// <param name="lineBreakInQuotedFieldIsBadData"></param>
+ public LineBreakInQuotedFieldIsBadDataAttribute(bool lineBreakInQuotedFieldIsBadData)
+ {
+ LineBreakInQuotedFieldIsBadData = lineBreakInQuotedFieldIsBadData;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.LineBreakInQuotedFieldIsBadData = LineBreakInQuotedFieldIsBadData;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MaxFieldSizeAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MaxFieldSizeAttribute.cs
new file mode 100644
index 0000000..1d5c837
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MaxFieldSizeAttribute.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Gets or sets the maximum size of a field.
+ /// Defaults to 0, indicating maximum field size is not checked.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class MaxFieldSizeAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets or sets the maximum size of a field.
+ /// </summary>
+ public double MaxFieldSize { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the maximum size of a field.
+ /// </summary>
+ /// <param name="maxFieldSize"></param>
+ public MaxFieldSizeAttribute(double maxFieldSize)
+ {
+ MaxFieldSize = maxFieldSize;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.MaxFieldSize = MaxFieldSize;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MemberTypesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MemberTypesAttribute.cs
new file mode 100644
index 0000000..e07e86f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MemberTypesAttribute.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The member types that are used when auto mapping.
+ /// MemberTypes are flags, so you can choose more than one.
+ /// Default is Properties.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class MemberTypesAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// The member types that are used when auto mapping.
+ /// MemberTypes are flags, so you can choose more than one.
+ /// Default is Properties.
+ /// </summary>
+ public MemberTypes MemberTypes { get; private set; }
+
+ /// <summary>
+ /// The member types that are used when auto mapping.
+ /// MemberTypes are flags, so you can choose more than one.
+ /// Default is Properties.
+ /// </summary>
+ public MemberTypesAttribute(MemberTypes memberTypes)
+ {
+ MemberTypes = memberTypes;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.MemberTypes = MemberTypes;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ModeAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ModeAttribute.cs
new file mode 100644
index 0000000..448a543
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ModeAttribute.cs
@@ -0,0 +1,38 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The mode.
+ /// See <see cref="CsvMode"/> for more details.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class ModeAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// The mode.
+ /// See <see cref="CsvMode"/> for more details.
+ /// </summary>
+ public CsvMode Mode { get; private set; }
+
+ /// <summary>
+ /// The mode.
+ /// See <see cref="CsvMode"/> for more details.
+ /// </summary>
+ /// <param name="mode"></param>
+ public ModeAttribute(CsvMode mode)
+ {
+ Mode = mode;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.Mode = Mode;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameAttribute.cs
new file mode 100644
index 0000000..f1220e4
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameAttribute.cs
@@ -0,0 +1,77 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// When reading, is used to get the field
+ /// at the index of the name if there was a
+ /// header specified. It will look for the
+ /// first name match in the order listed.
+ /// When writing, sets the name of the
+ /// field in the header record.
+ /// The first name will be used.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class NameAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the names.
+ /// </summary>
+ public string[] Names { get; private set; }
+
+ /// <summary>
+ /// When reading, is used to get the field
+ /// at the index of the name if there was a
+ /// header specified. It will look for the
+ /// first name match in the order listed.
+ /// When writing, sets the name of the
+ /// field in the header record.
+ /// The first name will be used.
+ /// </summary>
+ /// <param name="name">The name</param>
+ public NameAttribute(string name)
+ {
+ Names = new string[] { name };
+ }
+
+ /// <summary>
+ /// When reading, is used to get the field
+ /// at the index of the name if there was a
+ /// header specified. It will look for the
+ /// first name match in the order listed.
+ /// When writing, sets the name of the
+ /// field in the header record.
+ /// The first name will be used.
+ /// </summary>
+ /// <param name="names">The names.</param>
+ public NameAttribute(params string[] names)
+ {
+ if (names == null || names.Length == 0)
+ {
+ throw new ArgumentNullException(nameof(names));
+ }
+
+ Names = names;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.Names.Clear();
+ memberMap.Data.Names.AddRange(Names);
+ memberMap.Data.IsNameSet = true;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.Names.Clear();
+ parameterMap.Data.Names.AddRange(Names);
+ parameterMap.Data.IsNameSet = true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameIndexAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameIndexAttribute.cs
new file mode 100644
index 0000000..e3d1dfa
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameIndexAttribute.cs
@@ -0,0 +1,45 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// When reading, is used to get the
+ /// index of the name used when there
+ /// are multiple names that are the same.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class NameIndexAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// The name index.
+ /// </summary>
+ public int NameIndex { get; private set; }
+
+ /// <summary>
+ /// When reading, is used to get the
+ /// index of the name used when there
+ /// are multiple names that are the same.
+ /// </summary>
+ /// <param name="nameIndex">The name index.</param>
+ public NameIndexAttribute(int nameIndex)
+ {
+ NameIndex = nameIndex;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.NameIndex = NameIndex;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.NameIndex = NameIndex;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NewLineAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NewLineAttribute.cs
new file mode 100644
index 0000000..a2bdbd2
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NewLineAttribute.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class NewLineAttribute : Attribute, IClassMapper
+ {
+ /// 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.
+ public string NewLine { get; private set; }
+
+ /// 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.
+ public NewLineAttribute(string newLine)
+ {
+ NewLine = newLine;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.NewLine = NewLine;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NullValuesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NullValuesAttribute.cs
new file mode 100644
index 0000000..8c87e28
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NullValuesAttribute.cs
@@ -0,0 +1,52 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The string values used to represent null when converting.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class NullValuesAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the null values.
+ /// </summary>
+ public string[] NullValues { get; private set; }
+
+ /// <summary>
+ /// The string values used to represent null when converting.
+ /// </summary>
+ /// <param name="nullValue">The null values.</param>
+ public NullValuesAttribute(string nullValue)
+ {
+ NullValues = new string[] { nullValue };
+ }
+
+ /// <summary>
+ /// The string values used to represent null when converting.
+ /// </summary>
+ /// <param name="nullValues">The null values.</param>
+ public NullValuesAttribute(params string[] nullValues)
+ {
+ NullValues = nullValues;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.NullValues.Clear();
+ memberMap.Data.TypeConverterOptions.NullValues.AddRange(NullValues);
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.NullValues.Clear();
+ parameterMap.Data.TypeConverterOptions.NullValues.AddRange(NullValues);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NumberStylesAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NumberStylesAttribute.cs
new file mode 100644
index 0000000..1cd37fb
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NumberStylesAttribute.cs
@@ -0,0 +1,44 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The <see cref="NumberStyles"/> to use when type converting.
+ /// This is used when doing any number conversions.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class NumberStylesAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the number styles.
+ /// </summary>
+ public NumberStyles NumberStyles { get; private set; }
+
+ /// <summary>
+ /// The <see cref="NumberStyles"/> to use when type converting.
+ /// This is used when doing any number conversions.
+ /// </summary>
+ /// <param name="numberStyles">The number styles.</param>
+ public NumberStylesAttribute(NumberStyles numberStyles)
+ {
+ NumberStyles = numberStyles;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverterOptions.NumberStyles = NumberStyles;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverterOptions.NumberStyles = NumberStyles;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/OptionalAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/OptionalAttribute.cs
new file mode 100644
index 0000000..5348c85
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/OptionalAttribute.cs
@@ -0,0 +1,27 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Ignore the member when reading if no matching field name can be found.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class OptionalAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.IsOptional = true;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.IsOptional = true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ProcessFieldBufferSizeAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ProcessFieldBufferSizeAttribute.cs
new file mode 100644
index 0000000..81f6178
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ProcessFieldBufferSizeAttribute.cs
@@ -0,0 +1,36 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The size of the buffer used when processing fields.
+ /// Default is 1024.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class ProcessFieldBufferSizeAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// The size of the buffer used when processing fields.
+ /// </summary>
+ public int ProcessFieldBufferSize { get; private set; }
+
+ /// <summary>
+ /// The size of the buffer used when processing fields.
+ /// </summary>
+ /// <param name="processFieldBufferSize"></param>
+ public ProcessFieldBufferSizeAttribute(int processFieldBufferSize)
+ {
+ ProcessFieldBufferSize = processFieldBufferSize;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.ProcessFieldBufferSize = ProcessFieldBufferSize;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/QuoteAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/QuoteAttribute.cs
new file mode 100644
index 0000000..93b5887
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/QuoteAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The character used to quote fields.
+ /// </summary>
+ [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
+ public class QuoteAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets the character used to quote fields.
+ /// </summary>
+ public char Quote { get; private set; }
+
+ /// <summary>
+ /// The character used to quote fields.
+ /// </summary>
+ /// <param name="quote">The quote character.</param>
+ public QuoteAttribute( char quote )
+ {
+ Quote = quote;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.Quote = Quote;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TrimOptionsAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TrimOptionsAttribute.cs
new file mode 100644
index 0000000..1b2f645
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TrimOptionsAttribute.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// The fields trimming options.
+ /// </summary>
+ [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
+ public class TrimOptionsAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Gets the fields trimming options.
+ /// </summary>
+ public TrimOptions TrimOptions { get; private set; }
+
+ /// <summary>
+ /// The fields trimming options.
+ /// </summary>
+ /// <param name="trimOptions">The TrimOptions.</param>
+ public TrimOptionsAttribute( TrimOptions trimOptions )
+ {
+ TrimOptions = trimOptions;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.TrimOptions = TrimOptions;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TypeConverterAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TypeConverterAttribute.cs
new file mode 100644
index 0000000..f3900ec
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TypeConverterAttribute.cs
@@ -0,0 +1,57 @@
+// Copyright 2009-2022 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.TypeConversion;
+using System;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public class TypeConverterAttribute : Attribute, IMemberMapper, IParameterMapper
+ {
+ /// <summary>
+ /// Gets the type converter.
+ /// </summary>
+ public ITypeConverter TypeConverter { get; private set; }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <param name="typeConverterType">The type of the <see cref="ITypeConverter"/>.</param>
+ public TypeConverterAttribute(Type typeConverterType) : this(typeConverterType, new object[0]) { }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <param name="typeConverterType">The type of the <see cref="ITypeConverter"/>.</param>
+ /// <param name="constructorArgs">Type constructor arguments for the type converter.</param>
+ public TypeConverterAttribute(Type typeConverterType, params object[] constructorArgs)
+ {
+ if (typeConverterType == null)
+ {
+ throw new ArgumentNullException(nameof(typeConverterType));
+ }
+
+ TypeConverter = ObjectResolver.Current.Resolve(typeConverterType, constructorArgs) as ITypeConverter ?? throw new ArgumentException($"Type '{typeConverterType.FullName}' does not implement {nameof(ITypeConverter)}");
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(MemberMap memberMap)
+ {
+ memberMap.Data.TypeConverter = TypeConverter;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(ParameterMap parameterMap)
+ {
+ parameterMap.Data.TypeConverter = TypeConverter;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/UseNewObjectForNullReferenceMembersAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/UseNewObjectForNullReferenceMembersAttribute.cs
new file mode 100644
index 0000000..6bfbf37
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/UseNewObjectForNullReferenceMembersAttribute.cs
@@ -0,0 +1,47 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class UseNewObjectForNullReferenceMembersAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// 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.
+ /// </summary>
+ public bool UseNewObjectForNullReferenceMembers { get; private set; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="useNewObjectForNullReferenceMembers">The value.</param>
+ public UseNewObjectForNullReferenceMembersAttribute(bool useNewObjectForNullReferenceMembers)
+ {
+ UseNewObjectForNullReferenceMembers = useNewObjectForNullReferenceMembers;
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.UseNewObjectForNullReferenceMembers = UseNewObjectForNullReferenceMembers;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/WhiteSpaceCharsAttribute.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/WhiteSpaceCharsAttribute.cs
new file mode 100644
index 0000000..ef8f7cb
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/WhiteSpaceCharsAttribute.cs
@@ -0,0 +1,41 @@
+// Copyright 2009-2022 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;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace CsvHelper.Configuration.Attributes
+{
+ /// <summary>
+ /// Characters considered whitespace.
+ /// Used when trimming fields.
+ /// Default is [' '].
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public class WhiteSpaceCharsAttribute : Attribute, IClassMapper
+ {
+ /// <summary>
+ /// Characters considered whitespace.
+ /// Used when trimming fields.
+ /// </summary>
+ public char[] WhiteSpaceChars { get; private set; }
+
+ /// <summary>
+ /// Characters considered whitespace.
+ /// Used when trimming fields.
+ /// </summary>
+ /// <param name="whiteSpaceChars"></param>
+ public WhiteSpaceCharsAttribute(string whiteSpaceChars)
+ {
+ WhiteSpaceChars = Regex.Split(whiteSpaceChars, @"\s").Select(s => s[0]).ToArray();
+ }
+
+ /// <inheritdoc />
+ public void ApplyTo(CsvConfiguration configuration)
+ {
+ configuration.WhiteSpaceChars = WhiteSpaceChars;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap.cs
new file mode 100644
index 0000000..b000693
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap.cs
@@ -0,0 +1,648 @@
+// Copyright 2009-2022 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.TypeConversion;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+namespace CsvHelper.Configuration
+{
+ ///<summary>
+ /// Maps class members to CSV fields.
+ ///</summary>
+ public abstract class ClassMap
+ {
+ private static readonly List<Type> enumerableConverters = new List<Type>
+ {
+ typeof(ArrayConverter),
+ typeof(CollectionGenericConverter),
+ typeof(EnumerableConverter),
+ typeof(IDictionaryConverter),
+ typeof(IDictionaryGenericConverter),
+ typeof(IEnumerableConverter),
+ typeof(IEnumerableGenericConverter)
+ };
+
+ /// <summary>
+ /// The type of the class this map is for.
+ /// </summary>
+ public virtual Type ClassType { get; private set; }
+
+ /// <summary>
+ /// The class constructor parameter mappings.
+ /// </summary>
+ public virtual List<ParameterMap> ParameterMaps { get; } = new List<ParameterMap>();
+
+ /// <summary>
+ /// The class member mappings.
+ /// </summary>
+ public virtual MemberMapCollection MemberMaps { get; } = new MemberMapCollection();
+
+ /// <summary>
+ /// The class member reference mappings.
+ /// </summary>
+ public virtual MemberReferenceMapCollection ReferenceMaps { get; } = new MemberReferenceMapCollection();
+
+ /// <summary>
+ /// Allow only internal creation of CsvClassMap.
+ /// </summary>
+ /// <param name="classType">The type of the class this map is for.</param>
+ internal ClassMap(Type classType)
+ {
+ ClassType = classType;
+ }
+
+ /// <summary>
+ /// Maps a member to a CSV field.
+ /// </summary>
+ /// <param name="classType">The type of the class this map is for. This may not be the same type
+ /// as the member.DeclaringType or the current ClassType due to nested member mappings.</param>
+ /// <param name="member">The member to map.</param>
+ /// <param name="useExistingMap">If true, an existing map will be used if available.
+ /// If false, a new map is created for the same member.</param>
+ /// <returns>The member mapping.</returns>
+ public MemberMap Map(Type classType, MemberInfo member, bool useExistingMap = true)
+ {
+ if (useExistingMap)
+ {
+ var existingMap = MemberMaps.Find(member);
+ if (existingMap != null)
+ {
+ return existingMap;
+ }
+ }
+
+ var memberMap = MemberMap.CreateGeneric(classType, member);
+ memberMap.Data.Index = GetMaxIndex() + 1;
+ MemberMaps.Add(memberMap);
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// Maps a non-member to a CSV field. This allows for writing
+ /// data that isn't mapped to a class member.
+ /// </summary>
+ /// <returns>The member mapping.</returns>
+ public virtual MemberMap<object, object> Map()
+ {
+ var memberMap = new MemberMap<object, object>(null);
+ memberMap.Data.Index = GetMaxIndex() + 1;
+ MemberMaps.Add(memberMap);
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// Maps a member to another class map.
+ /// </summary>
+ /// <param name="classMapType">The type of the class map.</param>
+ /// <param name="member">The member.</param>
+ /// <param name="constructorArgs">Constructor arguments used to create the reference map.</param>
+ /// <returns>The reference mapping for the member.</returns>
+ public virtual MemberReferenceMap References(Type classMapType, MemberInfo member, params object[] constructorArgs)
+ {
+ if (!typeof(ClassMap).IsAssignableFrom(classMapType))
+ {
+ throw new InvalidOperationException($"Argument {nameof(classMapType)} is not a CsvClassMap.");
+ }
+
+ var existingMap = ReferenceMaps.Find(member);
+
+ if (existingMap != null)
+ {
+ return existingMap;
+ }
+
+ var map = (ClassMap)ObjectResolver.Current.Resolve(classMapType, constructorArgs);
+ map.ReIndex(GetMaxIndex() + 1);
+ var reference = new MemberReferenceMap(member, map);
+ ReferenceMaps.Add(reference);
+
+ return reference;
+ }
+
+ /// <summary>
+ /// Maps a constructor parameter to a CSV field.
+ /// </summary>
+ /// <param name="name">The name of the constructor parameter.</param>
+ public virtual ParameterMap Parameter(string name)
+ {
+ if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name));
+
+ var args = new GetConstructorArgs(ClassType);
+
+ return Parameter(() => ConfigurationFunctions.GetConstructor(args), name);
+ }
+
+ /// <summary>
+ /// Maps a constructor parameter to a CSV field.
+ /// </summary>
+ /// <param name="getConstructor">A function that returns the <see cref="ConstructorInfo"/> for the constructor.</param>
+ /// <param name="name">The name of the constructor parameter.</param>
+ public virtual ParameterMap Parameter(Func<ConstructorInfo> getConstructor, string name)
+ {
+ if (getConstructor == null) throw new ArgumentNullException(nameof(getConstructor));
+ if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name));
+
+ var constructor = getConstructor();
+ var parameters = constructor.GetParameters();
+ var parameter = parameters.SingleOrDefault(p => p.Name == name);
+ if (parameter == null)
+ {
+ throw new ConfigurationException($"Constructor {constructor.GetDefinition()} doesn't contain a paramter with name '{name}'.");
+ }
+
+ return Parameter(constructor, parameter);
+ }
+
+ /// <summary>
+ /// Maps a constructor parameter to a CSV field.
+ /// </summary>
+ /// <param name="constructor">The <see cref="ConstructorInfo"/> for the constructor.</param>
+ /// <param name="parameter">The <see cref="ParameterInfo"/> for the constructor parameter.</param>
+ public virtual ParameterMap Parameter(ConstructorInfo constructor, ParameterInfo parameter)
+ {
+ if (constructor == null) throw new ArgumentNullException(nameof(constructor));
+ if (parameter == null) throw new ArgumentNullException(nameof(parameter));
+
+ if (!constructor.GetParameters().Contains(parameter))
+ {
+ throw new ConfigurationException($"Constructor {constructor.GetDefinition()} doesn't contain parameter '{parameter.GetDefinition()}'.");
+ }
+
+ var parameterMap = new ParameterMap(parameter);
+ parameterMap.Data.Index = GetMaxIndex(isParameter: true) + 1;
+ ParameterMaps.Add(parameterMap);
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// Auto maps all members for the given type. If a member
+ /// is mapped again it will override the existing map.
+ /// </summary>
+ /// <param name="culture">The culture.</param>
+ public virtual void AutoMap(CultureInfo culture)
+ {
+ AutoMap(new CsvConfiguration(culture));
+ }
+
+ /// <summary>
+ /// Auto maps all members for the given type. If a member
+ /// is mapped again it will override the existing map.
+ /// </summary>
+ /// <param name="configuration">The configuration.</param>
+ public virtual void AutoMap(CsvConfiguration configuration)
+ {
+ AutoMap(new CsvContext(configuration));
+ }
+
+ /// <summary>
+ /// Auto maps all members for the given type. If a member
+ /// is mapped again it will override the existing map.
+ /// </summary>
+ /// <param name="context">The context.</param>
+ public virtual void AutoMap(CsvContext context)
+ {
+ var type = GetGenericType();
+ if (typeof(IEnumerable).IsAssignableFrom(type))
+ {
+ throw new ConfigurationException("Types that inherit IEnumerable cannot be auto mapped. " +
+ "Did you accidentally call GetRecord or WriteRecord which " +
+ "acts on a single record instead of calling GetRecords or " +
+ "WriteRecords which acts on a list of records?");
+ }
+
+ var mapParents = new LinkedList<Type>();
+ var args = new ShouldUseConstructorParametersArgs(type);
+ if (context.Configuration.ShouldUseConstructorParameters(args))
+ {
+ // This type doesn't have a parameterless constructor so we can't create an
+ // instance and set it's member. Constructor parameters need to be created
+ // instead. Writing only uses getters, so members will also be mapped
+ // for writing purposes.
+ AutoMapConstructorParameters(this, context, mapParents);
+ }
+
+ AutoMapMembers(this, context, mapParents);
+ }
+
+ /// <summary>
+ /// Get the largest index for the
+ /// members and references.
+ /// </summary>
+ /// <returns>The max index.</returns>
+ public virtual int GetMaxIndex(bool isParameter = false)
+ {
+ if (isParameter)
+ {
+ return ParameterMaps.Select(parameterMap => parameterMap.GetMaxIndex()).DefaultIfEmpty(-1).Max();
+ }
+
+ if (MemberMaps.Count == 0 && ReferenceMaps.Count == 0)
+ {
+ return -1;
+ }
+
+ var indexes = new List<int>();
+ if (MemberMaps.Count > 0)
+ {
+ indexes.Add(MemberMaps.Max(pm => pm.Data.Index));
+ }
+
+ if (ReferenceMaps.Count > 0)
+ {
+ indexes.AddRange(ReferenceMaps.Select(referenceMap => referenceMap.GetMaxIndex()));
+ }
+
+ return indexes.Max();
+ }
+
+ /// <summary>
+ /// Resets the indexes based on the given start index.
+ /// </summary>
+ /// <param name="indexStart">The index start.</param>
+ /// <returns>The last index + 1.</returns>
+ public virtual int ReIndex(int indexStart = 0)
+ {
+ foreach (var parameterMap in ParameterMaps)
+ {
+ parameterMap.Data.Index = indexStart + parameterMap.Data.Index;
+ }
+
+ foreach (var memberMap in MemberMaps)
+ {
+ if (!memberMap.Data.IsIndexSet)
+ {
+ memberMap.Data.Index = indexStart + memberMap.Data.Index;
+ }
+ }
+
+ foreach (var referenceMap in ReferenceMaps)
+ {
+ indexStart = referenceMap.Data.Mapping.ReIndex(indexStart);
+ }
+
+ return indexStart;
+ }
+
+ /// <summary>
+ /// Auto maps the given map and checks for circular references as it goes.
+ /// </summary>
+ /// <param name="map">The map to auto map.</param>
+ /// <param name="context">The context.</param>
+ /// <param name="mapParents">The list of parents for the map.</param>
+ /// <param name="indexStart">The index starting point.</param>
+ protected virtual void AutoMapMembers(ClassMap map, CsvContext context, LinkedList<Type> mapParents, int indexStart = 0)
+ {
+ var type = map.GetGenericType();
+
+ var flags = BindingFlags.Instance | BindingFlags.Public;
+ if (context.Configuration.IncludePrivateMembers)
+ {
+ flags = flags | BindingFlags.NonPublic;
+ }
+
+ var members = new List<MemberInfo>();
+ if ((context.Configuration.MemberTypes & MemberTypes.Properties) == MemberTypes.Properties)
+ {
+ // We need to go up the declaration tree and find the actual type the property
+ // exists on and use that PropertyInfo instead. This is so we can get the private
+ // set method for the property.
+ var properties = new List<PropertyInfo>();
+ foreach (var property in ReflectionHelper.GetUniqueProperties(type, flags))
+ {
+ if (properties.Any(p => p.Name == property.Name))
+ {
+ // Multiple properties could have the same name if a child class property
+ // is hiding a parent class property by using `new`. It's possible that
+ // the order of the properties returned
+ continue;
+ }
+
+ properties.Add(ReflectionHelper.GetDeclaringProperty(type, property, flags));
+ }
+
+ members.AddRange(properties);
+ }
+
+ if ((context.Configuration.MemberTypes & MemberTypes.Fields) == MemberTypes.Fields)
+ {
+ // We need to go up the declaration tree and find the actual type the field
+ // exists on and use that FieldInfo instead.
+ var fields = new List<MemberInfo>();
+ foreach (var field in ReflectionHelper.GetUniqueFields(type, flags))
+ {
+ if (fields.Any(p => p.Name == field.Name))
+ {
+ // Multiple fields could have the same name if a child class field
+ // is hiding a parent class field by using `new`. It's possible that
+ // the order of the fields returned
+ continue;
+ }
+
+ if (!field.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any())
+ {
+ fields.Add(ReflectionHelper.GetDeclaringField(type, field, flags));
+ }
+ }
+
+ members.AddRange(fields);
+ }
+
+ foreach (var member in members)
+ {
+ if (member.GetCustomAttribute<IgnoreAttribute>() != null)
+ {
+ // Ignore this member including its tree if it's a reference.
+ continue;
+ }
+
+ var typeConverterType = context.TypeConverterCache.GetConverter(member).GetType();
+
+ if (context.Configuration.HasHeaderRecord && enumerableConverters.Contains(typeConverterType))
+ {
+ // Enumerable converters can't write the header properly, so skip it.
+ continue;
+ }
+
+ var memberTypeInfo = member.MemberType().GetTypeInfo();
+ var isDefaultConverter = typeConverterType == typeof(DefaultTypeConverter);
+ if (isDefaultConverter)
+ {
+ // If the type is not one covered by our type converters
+ // and it has a parameterless constructor, create a
+ // reference map for it.
+
+ if (context.Configuration.IgnoreReferences)
+ {
+ continue;
+ }
+
+ if (CheckForCircularReference(member.MemberType(), mapParents))
+ {
+ continue;
+ }
+
+ mapParents.AddLast(type);
+ var refMapType = typeof(DefaultClassMap<>).MakeGenericType(member.MemberType());
+ var refMap = (ClassMap)ObjectResolver.Current.Resolve(refMapType);
+
+ if (memberTypeInfo.HasConstructor() && !memberTypeInfo.HasParameterlessConstructor() && !memberTypeInfo.IsUserDefinedStruct())
+ {
+ AutoMapConstructorParameters(refMap, context, mapParents, Math.Max(map.GetMaxIndex() + 1, indexStart));
+ }
+
+ // Need to use Max here for nested types.
+ AutoMapMembers(refMap, context, mapParents, Math.Max(map.GetMaxIndex() + 1, indexStart));
+ mapParents.Drop(mapParents.Find(type));
+
+ if (refMap.MemberMaps.Count > 0 || refMap.ReferenceMaps.Count > 0)
+ {
+ var referenceMap = new MemberReferenceMap(member, refMap);
+ if (context.Configuration.ReferenceHeaderPrefix != null)
+ {
+ var args = new ReferenceHeaderPrefixArgs(member.MemberType(), member.Name);
+ referenceMap.Data.Prefix = context.Configuration.ReferenceHeaderPrefix(args);
+ }
+
+ ApplyAttributes(referenceMap);
+
+ map.ReferenceMaps.Add(referenceMap);
+ }
+ }
+ else
+ {
+ // Only add the member map if it can be converted later on.
+ // If the member will use the default converter, don't add it because
+ // we don't want the .ToString() value to be used when auto mapping.
+
+ // Use the top of the map tree. This will maps that have been auto mapped
+ // to later on get a reference to a map by doing map.Map( m => m.A.B.C.Id )
+ // and it will return the correct parent map type of A instead of C.
+ var classType = mapParents.First?.Value ?? map.ClassType;
+ var memberMap = MemberMap.CreateGeneric(classType, member);
+
+ // Use global values as the starting point.
+ memberMap.Data.TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions(), context.TypeConverterOptionsCache.GetOptions(member.MemberType()), memberMap.Data.TypeConverterOptions);
+ memberMap.Data.Index = map.GetMaxIndex() + 1;
+
+ ApplyAttributes(memberMap);
+
+ map.MemberMaps.Add(memberMap);
+ }
+ }
+
+ map.ReIndex(indexStart);
+ }
+
+ /// <summary>
+ /// Auto maps the given map using constructor parameters.
+ /// </summary>
+ /// <param name="map">The map.</param>
+ /// <param name="context">The context.</param>
+ /// <param name="mapParents">The list of parents for the map.</param>
+ /// <param name="indexStart">The index starting point.</param>
+ protected virtual void AutoMapConstructorParameters(ClassMap map, CsvContext context, LinkedList<Type> mapParents, int indexStart = 0)
+ {
+ var type = map.GetGenericType();
+ var args = new GetConstructorArgs(map.ClassType);
+ var constructor = context.Configuration.GetConstructor(args);
+ var parameters = constructor.GetParameters();
+
+ foreach (var parameter in parameters)
+ {
+ var parameterMap = new ParameterMap(parameter);
+
+ if (parameter.GetCustomAttributes<IgnoreAttribute>(true).Any() || parameter.GetCustomAttributes<ConstantAttribute>(true).Any())
+ {
+ // If there is an IgnoreAttribute or ConstantAttribute, we still need to add a map because a constructor requires
+ // all parameters to be present. A default value will be used later on.
+
+ ApplyAttributes(parameterMap);
+ map.ParameterMaps.Add(parameterMap);
+ continue;
+ }
+
+ var typeConverterType = context.TypeConverterCache.GetConverter(parameter.ParameterType).GetType();
+ var memberTypeInfo = parameter.ParameterType.GetTypeInfo();
+ var isDefaultConverter = typeConverterType == typeof(DefaultTypeConverter);
+ if (isDefaultConverter && (memberTypeInfo.HasParameterlessConstructor() || memberTypeInfo.IsUserDefinedStruct()))
+ {
+ // If the type is not one covered by our type converters
+ // and it has a parameterless constructor, create a
+ // reference map for it.
+
+ if (context.Configuration.IgnoreReferences)
+ {
+ throw new InvalidOperationException($"Configuration '{nameof(CsvConfiguration.IgnoreReferences)}' can't be true " +
+ "when using types without a default constructor. Constructor parameters " +
+ "are used and all members including references must be used.");
+ }
+
+ if (CheckForCircularReference(parameter.ParameterType, mapParents))
+ {
+ throw new InvalidOperationException($"A circular reference was detected in constructor paramter '{parameter.Name}'." +
+ "Since all parameters must be supplied for a constructor, this parameter can't be skipped.");
+ }
+
+ mapParents.AddLast(type);
+ var refMapType = typeof(DefaultClassMap<>).MakeGenericType(parameter.ParameterType);
+ var refMap = (ClassMap)ObjectResolver.Current.Resolve(refMapType);
+ AutoMapMembers(refMap, context, mapParents, Math.Max(map.GetMaxIndex(isParameter: true) + 1, indexStart));
+ mapParents.Drop(mapParents.Find(type));
+
+ var referenceMap = new ParameterReferenceMap(parameter, refMap);
+ if (context.Configuration.ReferenceHeaderPrefix != null)
+ {
+ var referenceHeaderPrefix = new ReferenceHeaderPrefixArgs(memberTypeInfo.MemberType(), memberTypeInfo.Name);
+ referenceMap.Data.Prefix = context.Configuration.ReferenceHeaderPrefix(referenceHeaderPrefix);
+ }
+
+ ApplyAttributes(referenceMap);
+
+ parameterMap.ReferenceMap = referenceMap;
+ }
+ else if (isDefaultConverter && context.Configuration.ShouldUseConstructorParameters(new ShouldUseConstructorParametersArgs(parameter.ParameterType)))
+ {
+ // If the type is not one covered by our type converters
+ // and it should use contructor parameters, create a
+ // constructor map for it.
+
+ mapParents.AddLast(type);
+ var constructorMapType = typeof(DefaultClassMap<>).MakeGenericType(parameter.ParameterType);
+ var constructorMap = (ClassMap)ObjectResolver.Current.Resolve(constructorMapType);
+ // Need to use Max here for nested types.
+ AutoMapConstructorParameters(constructorMap, context, mapParents, Math.Max(map.GetMaxIndex(isParameter: true) + 1, indexStart));
+ mapParents.Drop(mapParents.Find(type));
+
+ parameterMap.ConstructorTypeMap = constructorMap;
+ }
+ else
+ {
+ parameterMap.Data.TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions(), context.TypeConverterOptionsCache.GetOptions(parameter.ParameterType), parameterMap.Data.TypeConverterOptions);
+ parameterMap.Data.Index = map.GetMaxIndex(isParameter: true) + 1;
+
+ ApplyAttributes(parameterMap);
+ }
+
+ map.ParameterMaps.Add(parameterMap);
+ }
+
+ map.ReIndex(indexStart);
+ }
+
+ /// <summary>
+ /// Checks for circular references.
+ /// </summary>
+ /// <param name="type">The type to check for.</param>
+ /// <param name="mapParents">The list of parents to check against.</param>
+ /// <returns>A value indicating if a circular reference was found.
+ /// True if a circular reference was found, otherwise false.</returns>
+ protected virtual bool CheckForCircularReference(Type type, LinkedList<Type> mapParents)
+ {
+ if (mapParents.Count == 0)
+ {
+ return false;
+ }
+
+ var node = mapParents.Last;
+ while (true)
+ {
+ if (node?.Value == type)
+ {
+ return true;
+ }
+
+ node = node?.Previous;
+ if (node == null)
+ {
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Gets the generic type for this class map.
+ /// </summary>
+ protected virtual Type GetGenericType()
+ {
+ return GetType().GetTypeInfo().BaseType?.GetGenericArguments()[0] ?? throw new ConfigurationException();
+ }
+
+ /// <summary>
+ /// Applies attribute configurations to the map.
+ /// </summary>
+ /// <param name="parameterMap">The parameter map.</param>
+ protected virtual void ApplyAttributes(ParameterMap parameterMap)
+ {
+ var parameter = parameterMap.Data.Parameter;
+ var attributes = parameter.GetCustomAttributes().OfType<IParameterMapper>();
+
+ foreach (var attribute in attributes)
+ {
+ attribute.ApplyTo(parameterMap);
+ }
+ }
+
+ /// <summary>
+ /// Applies attribute configurations to the map.
+ /// </summary>
+ /// <param name="referenceMap">The parameter reference map.</param>
+ protected virtual void ApplyAttributes(ParameterReferenceMap referenceMap)
+ {
+ var parameter = referenceMap.Data.Parameter;
+ var attributes = parameter.GetCustomAttributes().OfType<IParameterReferenceMapper>();
+
+ foreach (var attribute in attributes)
+ {
+ attribute.ApplyTo(referenceMap);
+ }
+ }
+
+ /// <summary>
+ /// Applies attribute configurations to the map.
+ /// </summary>
+ /// <param name="memberMap">The member map.</param>
+ protected virtual void ApplyAttributes(MemberMap memberMap)
+ {
+ if (memberMap.Data.Member == null)
+ {
+ return;
+ }
+
+ var member = memberMap.Data.Member;
+ var attributes = member.GetCustomAttributes().OfType<IMemberMapper>();
+
+ foreach (var attribute in attributes)
+ {
+ attribute.ApplyTo(memberMap);
+ }
+ }
+
+ /// <summary>
+ /// Applies attribute configurations to the map.
+ /// </summary>
+ /// <param name="referenceMap">The member reference map.</param>
+ protected virtual void ApplyAttributes(MemberReferenceMap referenceMap)
+ {
+ var member = referenceMap.Data.Member;
+ var attributes = member.GetCustomAttributes().OfType<IMemberReferenceMapper>();
+
+ foreach (var attribute in attributes)
+ {
+ attribute.ApplyTo(referenceMap);
+ }
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapBuilder.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapBuilder.cs
new file mode 100644
index 0000000..fbe2e6a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapBuilder.cs
@@ -0,0 +1,432 @@
+// Copyright 2009-2022 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;
+using System.Linq.Expressions;
+using CsvHelper.TypeConversion;
+using System.Collections;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Has mapping capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ public interface IHasMap<TClass> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// Maps a member to a CSV field.
+ /// </summary>
+ /// <param name="expression">The member to map.</param>
+ /// <param name="useExistingMap">If true, an existing map will be used if available.
+ /// If false, a new map is created for the same member.</param>
+ /// <returns>The member mapping.</returns>
+ IHasMapOptions<TClass, TMember> Map<TMember>(Expression<Func<TClass, TMember>> expression, bool useExistingMap = true);
+ }
+
+ /// <summary>
+ /// Options after a mapping call.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasMapOptions<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasTypeConverter<TClass, TMember>,
+ IHasIndex<TClass, TMember>,
+ IHasName<TClass, TMember>,
+ IHasOptional<TClass, TMember>,
+ IHasConvertUsing<TClass, TMember>,
+ IHasDefault<TClass, TMember>,
+ IHasConstant<TClass, TMember>,
+ IHasValidate<TClass, TMember>
+ { }
+
+ /// <summary>
+ /// Has type converter capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasTypeConverter<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <param name="typeConverter">The TypeConverter to use.</param>
+ IHasTypeConverterOptions<TClass, TMember> TypeConverter(ITypeConverter typeConverter);
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <typeparam name="TConverter">The <see cref="System.Type"/> of the
+ /// <see cref="TypeConverter"/> to use.</typeparam>
+ IHasTypeConverterOptions<TClass, TMember> TypeConverter<TConverter>() where TConverter : ITypeConverter;
+ }
+
+ /// <summary>
+ /// Options after a type converter call.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasTypeConverterOptions<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasDefault<TClass, TMember>,
+ IHasValidate<TClass, TMember>
+ { }
+
+ /// <summary>
+ /// Has index capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasIndex<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// When reading, is used to get the field at
+ /// the given index. When writing, the fields
+ /// will be written in the order of the field
+ /// indexes.
+ /// </summary>
+ /// <param name="index">The index of the CSV field.</param>
+ /// <param name="indexEnd">The end index used when mapping to an <see cref="IEnumerable"/> member.</param>
+ IHasIndexOptions<TClass, TMember> Index(int index, int indexEnd = -1);
+ }
+
+ /// <summary>
+ /// Options after an index call.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasIndexOptions<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasTypeConverter<TClass, TMember>,
+ IHasName<TClass, TMember>,
+ IHasDefault<TClass, TMember>,
+ IHasValidate<TClass, TMember>
+ { }
+
+ /// <summary>
+ /// Has optional capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasOptional<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// Ignore the member when reading if no matching field name can be found.
+ /// </summary>
+ IHasOptionalOptions<TClass, TMember> Optional();
+ }
+
+ /// <summary>
+ /// Options after an optional call.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasOptionalOptions<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasTypeConverter<TClass, TMember>,
+ IHasName<TClass, TMember>,
+ IHasDefault<TClass, TMember>,
+ IHasValidate<TClass, TMember>
+ { }
+
+ /// <summary>
+ /// Has name capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasName<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// When reading, is used to get the field
+ /// at the index of the name if there was a
+ /// header specified. It will look for the
+ /// first name match in the order listed.
+ /// When writing, sets the name of the
+ /// field in the header record.
+ /// The first name will be used.
+ /// </summary>
+ /// <param name="names">The possible names of the CSV field.</param>
+ IHasNameOptions<TClass, TMember> Name(params string[] names);
+ }
+
+ /// <summary>
+ /// Options after a name call.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasNameOptions<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasTypeConverter<TClass, TMember>,
+ IHasNameIndex<TClass, TMember>,
+ IHasDefault<TClass, TMember>,
+ IHasValidate<TClass, TMember>
+ { }
+
+ /// <summary>
+ /// Has name index capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasNameIndex<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// When reading, is used to get the
+ /// index of the name used when there
+ /// are multiple names that are the same.
+ /// </summary>
+ /// <param name="index">The index of the name.</param>
+ IHasNameIndexOptions<TClass, TMember> NameIndex(int index);
+ }
+
+ /// <summary>
+ /// Options after a name index call.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasNameIndexOptions<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasTypeConverter<TClass, TMember>,
+ IHasDefault<TClass, TMember>,
+ IHasValidate<TClass, TMember>
+ { }
+
+ /// <summary>
+ /// Has convert using capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasConvertUsing<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// Specifies an expression to be used to convert data in the
+ /// row to the member.
+ /// </summary>
+ /// <param name="convertExpression">The convert expression.</param>
+ IHasMap<TClass> ConvertUsing(ConvertFromString<TMember> convertExpression);
+
+ /// <summary>
+ /// Specifies an expression to be used to convert the object
+ /// to a field.
+ /// </summary>
+ /// <param name="convertExpression">The convert expression.</param>
+ IHasMap<TClass> ConvertUsing(ConvertToString<TClass> convertExpression);
+ }
+
+ /// <summary>
+ /// Has default capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasDefault<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty.
+ /// </summary>
+ /// <param name="defaultValue">The default value.</param>
+ IHasDefaultOptions<TClass, TMember> Default(TMember defaultValue);
+
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty. This value is not type checked
+ /// and will use a <see cref="ITypeConverter"/> to convert
+ /// the field. This could potentially have runtime errors.
+ /// </summary>
+ /// <param name="defaultValue">The default value.</param>
+ IHasDefaultOptions<TClass, TMember> Default(string defaultValue);
+ }
+
+ /// <summary>
+ /// Options after a default call.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasDefaultOptions<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasValidate<TClass, TMember>
+ { }
+
+ /// <summary>
+ /// Has constant capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasConstant<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// The constant value that will be used for every record when
+ /// reading and writing. This value will always be used no matter
+ /// what other mapping configurations are specified.
+ /// </summary>
+ /// <param name="value">The constant value.</param>
+ IHasMap<TClass> Constant(TMember value);
+ }
+
+ /// <summary>
+ /// Has validate capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ /// <typeparam name="TMember">The member type.</typeparam>
+ public interface IHasValidate<TClass, TMember> : IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// The validate expression that will be called on every field when reading.
+ /// The expression should return true if the field is valid.
+ /// If false is returned, a <see cref="ValidationException"/>
+ /// will be thrown.
+ /// </summary>
+ /// <param name="validateExpression">The validation expression.</param>
+ IHasMap<TClass> Validate(Validate validateExpression);
+ }
+
+ /// <summary>
+ /// Has build capabilities.
+ /// </summary>
+ /// <typeparam name="TClass">The class type.</typeparam>
+ public interface IBuildableClass<TClass>
+ {
+ /// <summary>
+ /// Builds the <see cref="ClassMap{TClass}"/>.
+ /// </summary>
+ ClassMap<TClass> Build();
+ }
+
+ internal class ClassMapBuilder<TClass> : IHasMap<TClass>
+ {
+ private readonly ClassMap<TClass> map;
+
+ public ClassMapBuilder()
+ {
+ map = new BuilderClassMap<TClass>();
+ }
+
+ public IHasMapOptions<TClass, TMember> Map<TMember>(Expression<Func<TClass, TMember>> expression, bool useExistingMap = true)
+ {
+ return new MemberMapBuilder<TClass, TMember>(map, map.Map(expression, useExistingMap));
+ }
+
+ public ClassMap<TClass> Build()
+ {
+ return map;
+ }
+
+ private class BuilderClassMap<T> : ClassMap<T> { }
+ }
+
+ internal class MemberMapBuilder<TClass, TMember> :
+ IHasMap<TClass>,
+ IHasMapOptions<TClass, TMember>,
+ IHasTypeConverter<TClass, TMember>,
+ IHasTypeConverterOptions<TClass, TMember>,
+ IHasIndex<TClass, TMember>,
+ IHasIndexOptions<TClass, TMember>,
+ IHasName<TClass, TMember>,
+ IHasNameOptions<TClass, TMember>,
+ IHasNameIndex<TClass, TMember>,
+ IHasNameIndexOptions<TClass, TMember>,
+ IHasOptional<TClass, TMember>,
+ IHasOptionalOptions<TClass, TMember>,
+ IHasConvertUsing<TClass, TMember>,
+ IHasDefault<TClass, TMember>,
+ IHasDefaultOptions<TClass, TMember>,
+ IHasConstant<TClass, TMember>,
+ IHasValidate<TClass, TMember>
+ {
+ private readonly ClassMap<TClass> classMap;
+ private readonly MemberMap<TClass, TMember> memberMap;
+
+ public MemberMapBuilder(ClassMap<TClass> classMap, MemberMap<TClass, TMember> memberMap)
+ {
+ this.classMap = classMap;
+ this.memberMap = memberMap;
+ }
+
+#pragma warning disable CS0693 // Type parameter has the same name as the type parameter from outer type
+ public IHasMapOptions<TClass, TMember> Map<TMember>(Expression<Func<TClass, TMember>> expression, bool useExistingMap = true)
+ {
+ return new MemberMapBuilder<TClass, TMember>(classMap, classMap.Map(expression, useExistingMap));
+ }
+#pragma warning restore CS0693 // Type parameter has the same name as the type parameter from outer type
+
+ public IHasMap<TClass> ConvertUsing(ConvertFromString<TMember> convertExpression)
+ {
+ memberMap.Convert(convertExpression);
+ return this;
+ }
+
+ public IHasMap<TClass> ConvertUsing(ConvertToString<TClass> convertExpression)
+ {
+ memberMap.Convert(convertExpression);
+ return this;
+ }
+
+ public IHasDefaultOptions<TClass, TMember> Default(TMember defaultValue)
+ {
+ memberMap.Default(defaultValue);
+ return this;
+ }
+
+ public IHasDefaultOptions<TClass, TMember> Default(string defaultValue)
+ {
+ memberMap.Default(defaultValue);
+ return this;
+ }
+
+ public IHasIndexOptions<TClass, TMember> Index(int index, int indexEnd = -1)
+ {
+ memberMap.Index(index, indexEnd);
+ return this;
+ }
+
+ public IHasNameOptions<TClass, TMember> Name(params string[] names)
+ {
+ memberMap.Name(names);
+ return this;
+ }
+
+ public IHasNameIndexOptions<TClass, TMember> NameIndex(int index)
+ {
+ memberMap.NameIndex(index);
+ return this;
+ }
+
+ public IHasOptionalOptions<TClass, TMember> Optional()
+ {
+ memberMap.Optional();
+ return this;
+ }
+
+ public IHasTypeConverterOptions<TClass, TMember> TypeConverter(ITypeConverter typeConverter)
+ {
+ memberMap.TypeConverter(typeConverter);
+ return this;
+ }
+
+ public IHasTypeConverterOptions<TClass, TMember> TypeConverter<TConverter>() where TConverter : ITypeConverter
+ {
+ memberMap.TypeConverter<TConverter>();
+ return this;
+ }
+
+ public IHasMap<TClass> Constant(TMember value)
+ {
+ memberMap.Constant(value);
+ return this;
+ }
+
+ public IHasMap<TClass> Validate(Validate validateExpression)
+ {
+ memberMap.Validate(validateExpression);
+ return this;
+ }
+
+ public ClassMap<TClass> Build()
+ {
+ return classMap;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapCollection.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapCollection.cs
new file mode 100644
index 0000000..f66a284
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapCollection.cs
@@ -0,0 +1,188 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Collection that holds CsvClassMaps for record types.
+ /// </summary>
+ public class ClassMapCollection
+ {
+ private readonly Dictionary<Type, ClassMap> data = new Dictionary<Type, ClassMap>();
+ private readonly CsvContext context;
+
+ /// <summary>
+ /// Gets the <see cref="ClassMap"/> for the specified record type.
+ /// </summary>
+ /// <value>
+ /// The <see cref="ClassMap"/>.
+ /// </value>
+ /// <param name="type">The record type.</param>
+ /// <returns>The <see cref="ClassMap"/> for the specified record type.</returns>
+ public virtual ClassMap? this[Type type]
+ {
+ get
+ {
+ // Go up the inheritance tree to find the matching type.
+ // We can't use IsAssignableFrom because both a child
+ // and it's parent/grandparent/etc could be mapped.
+ var currentType = type;
+ while (true)
+ {
+ if (data.TryGetValue(currentType, out var map))
+ {
+ return map;
+ }
+
+ currentType = currentType.GetTypeInfo().BaseType;
+ if (currentType == null)
+ {
+ return null;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates a new instance using the given configuration.
+ /// </summary>
+ /// <param name="context">The context.</param>
+ public ClassMapCollection(CsvContext context)
+ {
+ this.context = context;
+ }
+
+ /// <summary>
+ /// Finds the <see cref="ClassMap"/> for the specified record type.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <returns>The <see cref="ClassMap"/> for the specified record type.</returns>
+ public virtual ClassMap<T>? Find<T>()
+ {
+ return (ClassMap<T>?)this[typeof(T)];
+ }
+
+ /// <summary>
+ /// Adds the specified map for it's record type. If a map
+ /// already exists for the record type, the specified
+ /// map will replace it.
+ /// </summary>
+ /// <param name="map">The map.</param>
+ internal virtual void Add(ClassMap map)
+ {
+ SetMapDefaults(map);
+
+ var type = GetGenericCsvClassMapType(map.GetType()).GetGenericArguments().First();
+
+ data[type] = map;
+ }
+
+ /// <summary>
+ /// Removes the class map.
+ /// </summary>
+ /// <param name="classMapType">The class map type.</param>
+ internal virtual void Remove(Type classMapType)
+ {
+ if (!typeof(ClassMap).IsAssignableFrom(classMapType))
+ {
+ throw new ArgumentException("The class map type must inherit from CsvClassMap.");
+ }
+
+ var type = GetGenericCsvClassMapType(classMapType).GetGenericArguments().First();
+
+ data.Remove(type);
+ }
+
+ /// <summary>
+ /// Removes all maps.
+ /// </summary>
+ internal virtual void Clear()
+ {
+ data.Clear();
+ }
+
+ /// <summary>
+ /// Goes up the inheritance tree to find the type instance of CsvClassMap{}.
+ /// </summary>
+ /// <param name="type">The type to traverse.</param>
+ /// <returns>The type that is CsvClassMap{}.</returns>
+ private Type GetGenericCsvClassMapType(Type type)
+ {
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(ClassMap<>))
+ {
+ return type;
+ }
+
+ return GetGenericCsvClassMapType(type.GetTypeInfo().BaseType);
+ }
+
+ /// <summary>
+ /// Sets defaults for the mapping tree. The defaults used
+ /// to be set inside the classes, but this didn't allow for
+ /// the TypeConverter to be created from the Configuration's
+ /// TypeConverterFactory.
+ /// </summary>
+ /// <param name="map">The map to set defaults on.</param>
+ private void SetMapDefaults(ClassMap map)
+ {
+ foreach (var parameterMap in map.ParameterMaps)
+ {
+ if (parameterMap.ConstructorTypeMap != null)
+ {
+ SetMapDefaults(parameterMap.ConstructorTypeMap);
+ }
+ else if (parameterMap.ReferenceMap != null)
+ {
+ SetMapDefaults(parameterMap.ReferenceMap.Data.Mapping);
+ }
+ else
+ {
+ if (parameterMap.Data.TypeConverter == null)
+ {
+ parameterMap.Data.TypeConverter = context.TypeConverterCache.GetConverter(parameterMap.Data.Parameter.ParameterType);
+ }
+
+ if (parameterMap.Data.Names.Count == 0)
+ {
+ parameterMap.Data.Names.Add(parameterMap.Data.Parameter.Name);
+ }
+ }
+ }
+
+ foreach (var memberMap in map.MemberMaps)
+ {
+ if (memberMap.Data.Member == null)
+ {
+ continue;
+ }
+
+ if (memberMap.Data.TypeConverter == null && memberMap.Data.ReadingConvertExpression == null && memberMap.Data.WritingConvertExpression == null)
+ {
+ memberMap.Data.TypeConverter = context.TypeConverterCache.GetConverter(memberMap.Data.Member.MemberType());
+ }
+
+ if (memberMap.Data.Names.Count == 0)
+ {
+ memberMap.Data.Names.Add(memberMap.Data.Member.Name);
+ }
+ }
+
+ foreach (var referenceMap in map.ReferenceMaps)
+ {
+ SetMapDefaults(referenceMap.Data.Mapping);
+
+ if (context.Configuration.ReferenceHeaderPrefix != null)
+ {
+ var args = new ReferenceHeaderPrefixArgs(referenceMap.Data.Member.MemberType(), referenceMap.Data.Member.Name);
+ referenceMap.Data.Prefix = context.Configuration.ReferenceHeaderPrefix(args);
+ }
+ }
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap`1.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap`1.cs
new file mode 100644
index 0000000..d14c317
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap`1.cs
@@ -0,0 +1,112 @@
+// Copyright 2009-2022 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;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Maps class members to CSV fields.
+ /// </summary>
+ /// <typeparam name="TClass">The <see cref="System.Type"/> of class to map.</typeparam>
+ public abstract class ClassMap<TClass> : ClassMap
+ {
+ /// <summary>
+ /// Creates an instance of <see cref="ClassMap{TClass}"/>.
+ /// </summary>
+ public ClassMap() : base(typeof(TClass)) { }
+
+ /// <summary>
+ /// Maps a member to a CSV field.
+ /// </summary>
+ /// <param name="expression">The member to map.</param>
+ /// <param name="useExistingMap">If true, an existing map will be used if available.
+ /// If false, a new map is created for the same member.</param>
+ /// <returns>The member mapping.</returns>
+ public virtual MemberMap<TClass, TMember> Map<TMember>(Expression<Func<TClass, TMember>> expression, bool useExistingMap = true)
+ {
+ var (classMap, member) = GetMemberMap(expression);
+ var memberMap = classMap.Map(typeof(TClass), member, useExistingMap); ;
+
+ return (MemberMap<TClass, TMember>)memberMap;
+ }
+
+ /// <summary>
+ /// Maps a member to a CSV field.
+ /// </summary>
+ /// <param name="expression">The member to map.</param>
+ /// <param name="useExistingMap">If true, an existing map will be used if available.
+ /// If false, a new map is created for the same member.</param>
+ /// <returns>The member mapping.</returns>
+ public virtual MemberMap Map<T>(Expression<Func<T, object>> expression, bool useExistingMap = true)
+ {
+ var (classMap, member) = GetMemberMap(expression);
+ var memberMap = classMap.Map(typeof(TClass), member, useExistingMap);
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// Meant for internal use only.
+ /// Maps a member to another class map. When this is used, accessing a property through
+ /// sub-property mapping later won't work. You can only use one or the other. When using
+ /// this, ConvertUsing will also not work.
+ /// </summary>
+ /// <typeparam name="TClassMap">The type of the class map.</typeparam>
+ /// <param name="expression">The expression.</param>
+ /// <param name="constructorArgs">Constructor arguments used to create the reference map.</param>
+ /// <returns>The reference mapping for the member.</returns>
+ public virtual MemberReferenceMap References<TClassMap>(Expression<Func<TClass, object>> expression, params object[] constructorArgs) where TClassMap : ClassMap
+ {
+ var member = ReflectionHelper.GetMember(expression);
+ return References(typeof(TClassMap), member, constructorArgs);
+ }
+
+ private (ClassMap, MemberInfo) GetMemberMap<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
+ {
+ var stack = ReflectionHelper.GetMembers(expression);
+ if (stack.Count == 0)
+ {
+ throw new InvalidOperationException($"No members were found in expression '{expression}'.");
+ }
+
+ ClassMap currentClassMap = this;
+ MemberInfo member;
+
+ if (stack.Count > 1)
+ {
+ // We need to add a reference map for every sub member.
+ while (stack.Count > 1)
+ {
+ member = stack.Pop();
+ Type mapType;
+ var property = member as PropertyInfo;
+ var field = member as FieldInfo;
+ if (property != null)
+ {
+ mapType = typeof(DefaultClassMap<>).MakeGenericType(property.PropertyType);
+ }
+ else if (field != null)
+ {
+ mapType = typeof(DefaultClassMap<>).MakeGenericType(field.FieldType);
+ }
+ else
+ {
+ throw new InvalidOperationException("The given expression was not a property or a field.");
+ }
+
+ var referenceMap = currentClassMap.References(mapType, member);
+ currentClassMap = referenceMap.Data.Mapping;
+ }
+ }
+
+ // Add the member map to the last reference map.
+ member = stack.Pop();
+
+ return (currentClassMap, member);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationException.cs
new file mode 100644
index 0000000..8a9bba1
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationException.cs
@@ -0,0 +1,36 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Represents configuration errors that occur.
+ /// </summary>
+ [Serializable]
+ public class ConfigurationException : CsvHelperException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConfigurationException"/> class.
+ /// </summary>
+ public ConfigurationException() { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConfigurationException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="message">The message that describes the error.</param>
+ public ConfigurationException( string message ) : base( message ) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConfigurationException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public ConfigurationException( string message, Exception innerException ) : base( message, innerException ) { }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationFunctions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationFunctions.cs
new file mode 100644
index 0000000..0cf7259
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationFunctions.cs
@@ -0,0 +1,267 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>Holds the default callback methods for delegate members of <c>CsvHelper.Configuration.Configuration</c>.</summary>
+ public static class ConfigurationFunctions
+ {
+ private static readonly char[] lineEndingChars = new char[] { '\r', '\n' };
+
+ /// <summary>
+ /// Throws a <see cref="ValidationException"/> if <see name="HeaderValidatedArgs.InvalidHeaders"/> is not empty.
+ /// </summary>
+ public static void HeaderValidated(HeaderValidatedArgs args)
+ {
+ if (args.InvalidHeaders.Count() == 0)
+ {
+ return;
+ }
+
+ var errorMessage = new StringBuilder();
+ foreach (var invalidHeader in args.InvalidHeaders)
+ {
+ errorMessage.AppendLine($"Header with name '{string.Join("' or '", invalidHeader.Names)}'[{invalidHeader.Index}] was not found.");
+ }
+
+ if (args.Context.Reader.HeaderRecord != null)
+ {
+ foreach (var header in args.Context.Reader.HeaderRecord)
+ {
+ errorMessage.AppendLine($"Headers: '{string.Join("', '", args.Context.Reader.HeaderRecord)}'");
+ }
+ }
+
+ var messagePostfix =
+ $"If you are expecting some headers to be missing and want to ignore this validation, " +
+ $"set the configuration {nameof(HeaderValidated)} to null. You can also change the " +
+ $"functionality to do something else, like logging the issue.";
+ errorMessage.AppendLine(messagePostfix);
+
+ throw new HeaderValidationException(args.Context, args.InvalidHeaders, errorMessage.ToString());
+ }
+
+ /// <summary>
+ /// Throws a <c>MissingFieldException</c>.
+ /// </summary>
+ public static void MissingFieldFound(MissingFieldFoundArgs args)
+ {
+ var messagePostfix = $"You can ignore missing fields by setting {nameof(MissingFieldFound)} to null.";
+
+ // Get by index.
+
+ if (args.HeaderNames == null || args.HeaderNames.Length == 0)
+ {
+ throw new MissingFieldException(args.Context, $"Field at index '{args.Index}' does not exist. {messagePostfix}");
+ }
+
+ // Get by name.
+
+ var indexText = args.Index > 0 ? $" at field index '{args.Index}'" : string.Empty;
+
+ if (args.HeaderNames.Length == 1)
+ {
+ throw new MissingFieldException(args.Context, $"Field with name '{args.HeaderNames[0]}'{indexText} does not exist. {messagePostfix}");
+ }
+
+ throw new MissingFieldException(args.Context, $"Field containing names '{string.Join("' or '", args.HeaderNames)}'{indexText} does not exist. {messagePostfix}");
+ }
+
+ /// <summary>
+ /// Throws a <see cref="BadDataException"/>.
+ /// </summary>
+ public static void BadDataFound(BadDataFoundArgs args)
+ {
+ throw new BadDataException(args.Field, args.RawRecord, args.Context, $"You can ignore bad data by setting {nameof(BadDataFound)} to null.");
+ }
+
+ /// <summary>
+ /// Throws the given <see name="ReadingExceptionOccurredArgs.Exception"/>.
+ /// </summary>
+ public static bool ReadingExceptionOccurred(ReadingExceptionOccurredArgs args)
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true if the field contains a <see cref="IWriterConfiguration.Quote"/>,
+ /// starts with a space, ends with a space, contains \r or \n, or contains
+ /// the <see cref="IWriterConfiguration.Delimiter"/>.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns><c>true</c> if the field should be quoted, otherwise <c>false</c>.</returns>
+ public static bool ShouldQuote(ShouldQuoteArgs args)
+ {
+ var config = args.Row.Configuration;
+
+ var shouldQuote = !string.IsNullOrEmpty(args.Field) &&
+ (
+ args.Field.Contains(config.Quote) // Contains quote
+ || args.Field[0] == ' ' // Starts with a space
+ || args.Field[args.Field.Length - 1] == ' ' // Ends with a space
+ || (config.Delimiter.Length > 0 && args.Field.Contains(config.Delimiter)) // Contains delimiter
+ || !config.IsNewLineSet && args.Field.IndexOfAny(lineEndingChars) > -1 // Contains line ending characters
+ || config.IsNewLineSet && args.Field.Contains(config.NewLine) // Contains newline
+ );
+
+ return shouldQuote;
+ }
+
+ /// <summary>
+ /// Returns the <see name="PrepareHeaderForMatchArgs.Header"/> as given.
+ /// </summary>
+ public static string PrepareHeaderForMatch(PrepareHeaderForMatchArgs args)
+ {
+ return args.Header;
+ }
+
+ /// <summary>
+ /// Returns <c>true</c> if <paramref name="args.ParameterType"/>:
+ /// 1. does not have a parameterless constructor
+ /// 2. has a constructor
+ /// 3. is not a value type
+ /// 4. is not a primitive
+ /// 5. is not an enum
+ /// 6. is not an interface
+ /// 7. TypeCode is an Object.
+ /// </summary>
+ public static bool ShouldUseConstructorParameters(ShouldUseConstructorParametersArgs args)
+ {
+ return !args.ParameterType.HasParameterlessConstructor()
+ && args.ParameterType.HasConstructor()
+ && !args.ParameterType.IsValueType
+ && !args.ParameterType.IsPrimitive
+ && !args.ParameterType.IsEnum
+ && !args.ParameterType.IsInterface
+ && Type.GetTypeCode(args.ParameterType) == TypeCode.Object;
+ }
+
+ /// <summary>
+ /// Returns the type's constructor with the most parameters.
+ /// If two constructors have the same number of parameters, then
+ /// there is no guarantee which one will be returned. If you have
+ /// that situation, you should probably implement this function yourself.
+ /// </summary>
+ public static ConstructorInfo GetConstructor(GetConstructorArgs args)
+ {
+ return args.ClassType.GetConstructorWithMostParameters();
+ }
+
+ /// <summary>
+ /// Returns the header name ran through <see cref="PrepareHeaderForMatch(PrepareHeaderForMatchArgs)"/>.
+ /// If no header exists, property names will be Field1, Field2, Field3, etc.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ public static string GetDynamicPropertyName(GetDynamicPropertyNameArgs args)
+ {
+ if (args.Context.Reader.HeaderRecord == null)
+ {
+ return $"Field{args.FieldIndex + 1}";
+ }
+
+ var header = args.Context.Reader.HeaderRecord[args.FieldIndex];
+ var prepareHeaderForMatchArgs = new PrepareHeaderForMatchArgs(header, args.FieldIndex);
+ header = args.Context.Reader.Configuration.PrepareHeaderForMatch(prepareHeaderForMatchArgs);
+
+ return header;
+ }
+
+ /// <summary>
+ /// Detects the delimiter based on the given text.
+ /// Return the detected delimiter or null if one wasn't found.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ public static string? GetDelimiter(GetDelimiterArgs args)
+ {
+ var text = args.Text;
+ var config = args.Configuration;
+
+ if (config.Mode == CsvMode.RFC4180)
+ {
+ // Remove text in between pairs of quotes.
+ text = Regex.Replace(text, $"{config.Quote}.*?{config.Quote}", string.Empty, RegexOptions.Singleline);
+ }
+ else if (config.Mode == CsvMode.Escape)
+ {
+ // Remove escaped characters.
+ text = Regex.Replace(text, $"({config.Escape}.)", string.Empty, RegexOptions.Singleline);
+ }
+
+ var newLine = config.NewLine;
+ if ((new[] { "\r\n", "\r", "\n" }).Contains(newLine))
+ {
+ newLine = "\r\n|\r|\n";
+ }
+
+ var lineDelimiterCounts = new List<Dictionary<string, int>>();
+ while (text.Length > 0)
+ {
+ // Since all escaped text has been removed, we can reliably read line by line.
+ var match = Regex.Match(text, newLine);
+ var line = match.Success ? text.Substring(0, match.Index + match.Length) : text;
+
+ var delimiterCounts = new Dictionary<string, int>();
+ foreach (var delimiter in config.DetectDelimiterValues)
+ {
+ // Escape regex special chars to use as regex pattern.
+ var pattern = Regex.Replace(delimiter, @"([.$^{\[(|)*+?\\])", "\\$1");
+ delimiterCounts[delimiter] = Regex.Matches(line, pattern).Count;
+ }
+
+ lineDelimiterCounts.Add(delimiterCounts);
+
+ text = match.Success ? text.Substring(match.Index + match.Length) : string.Empty;
+ }
+
+ if (lineDelimiterCounts.Count > 1)
+ {
+ // The last line isn't complete and can't be used to reliably detect a delimiter.
+ lineDelimiterCounts.Remove(lineDelimiterCounts.Last());
+ }
+
+ // Rank only the delimiters that appear on every line.
+ var delimiters =
+ (
+ from counts in lineDelimiterCounts
+ from count in counts
+ group count by count.Key into g
+ where g.All(x => x.Value > 0)
+ let sum = g.Sum(x => x.Value)
+ orderby sum descending
+ select new
+ {
+ Delimiter = g.Key,
+ Count = sum
+ }
+ ).ToList();
+
+ string? newDelimiter = null;
+ if (delimiters.Any(x => x.Delimiter == config.CultureInfo.TextInfo.ListSeparator) && lineDelimiterCounts.Count > 1)
+ {
+ // The culture's separator is on every line. Assume this is the delimiter.
+ newDelimiter = config.CultureInfo.TextInfo.ListSeparator;
+ }
+ else
+ {
+ // Choose the highest ranked delimiter.
+ newDelimiter = delimiters.Select(x => x.Delimiter).FirstOrDefault();
+ }
+
+ if (newDelimiter != null)
+ {
+ config.Validate();
+ }
+
+ return newDelimiter ?? config.Delimiter;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/CsvConfiguration.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/CsvConfiguration.cs
new file mode 100644
index 0000000..51636a2
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/CsvConfiguration.cs
@@ -0,0 +1,240 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using CsvHelper.Configuration.Attributes;
+using CsvHelper.Delegates;
+using CsvHelper.TypeConversion;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Configuration used for reading and writing CSV data.
+ /// </summary>
+ public record CsvConfiguration : IReaderConfiguration, IWriterConfiguration
+ {
+ private string newLine = "\r\n";
+
+ /// <inheritdoc/>
+ public virtual bool AllowComments { get; set; }
+
+ /// <inheritdoc/>
+ public virtual BadDataFound BadDataFound { get; set; } = ConfigurationFunctions.BadDataFound;
+
+ /// <inheritdoc/>
+ public virtual int BufferSize { get; set; } = 0x1000;
+
+ /// <inheritdoc/>
+ public virtual bool CacheFields { get; set; }
+
+ /// <inheritdoc/>
+ public virtual char Comment { get; set; } = '#';
+
+ /// <inheritdoc/>
+ public virtual bool CountBytes { get; set; }
+
+ /// <inheritdoc/>
+ public virtual CultureInfo CultureInfo { get; protected set; }
+
+ /// <inheritdoc/>
+ public virtual string Delimiter { get; set; }
+
+ /// <inheritdoc/>
+ public virtual bool DetectDelimiter { get; set; }
+
+ /// <inheritdoc/>
+ public virtual GetDelimiter GetDelimiter { get; set; } = ConfigurationFunctions.GetDelimiter;
+
+ /// <inheritdoc/>
+ public virtual string[] DetectDelimiterValues { get; set; } = new[] { ",", ";", "|", "\t" };
+
+ /// <inheritdoc/>
+ public virtual bool DetectColumnCountChanges { get; set; }
+
+ /// <inheritdoc/>
+ public virtual IComparer<string>? DynamicPropertySort { get; set; }
+
+ /// <inheritdoc/>
+ public virtual Encoding Encoding { get; set; } = Encoding.UTF8;
+
+ /// <inheritdoc/>
+ public virtual char Escape { get; set; } = '"';
+
+ /// <inheritdoc/>
+ public virtual bool ExceptionMessagesContainRawData { get; set; } = true;
+
+ /// <inheritdoc/>
+ public virtual GetConstructor GetConstructor { get; set; } = ConfigurationFunctions.GetConstructor;
+
+ /// <inheritdoc/>
+ public virtual GetDynamicPropertyName GetDynamicPropertyName { get; set; } = ConfigurationFunctions.GetDynamicPropertyName;
+
+ /// <inheritdoc/>
+ public virtual bool HasHeaderRecord { get; set; } = true;
+
+ /// <inheritdoc/>
+ public virtual HeaderValidated HeaderValidated { get; set; } = ConfigurationFunctions.HeaderValidated;
+
+ /// <inheritdoc/>
+ public virtual bool IgnoreBlankLines { get; set; } = true;
+
+ /// <inheritdoc/>
+ public virtual bool IgnoreReferences { get; set; }
+
+ /// <inheritdoc/>
+ public virtual bool IncludePrivateMembers { get; set; }
+
+ /// <inheritdoc/>
+ public virtual char[] InjectionCharacters { get; set; } = new[] { '=', '@', '+', '-', '\t', '\r' };
+
+ /// <inheritdoc/>
+ public virtual char InjectionEscapeCharacter { get; set; } = '\'';
+
+ /// <inheritdoc />
+ public virtual InjectionOptions InjectionOptions { get; set; }
+
+ /// <inheritdoc/>
+ public bool IsNewLineSet { get; private set; }
+
+ /// <inheritdoc/>
+ public virtual bool LineBreakInQuotedFieldIsBadData { get; set; }
+
+ /// <inheritdoc/>
+ public double MaxFieldSize { get; set; }
+
+ /// <inheritdoc/>
+ public virtual MemberTypes MemberTypes { get; set; } = MemberTypes.Properties;
+
+ /// <inheritdoc/>
+ public virtual MissingFieldFound MissingFieldFound { get; set; } = ConfigurationFunctions.MissingFieldFound;
+
+ /// <inheritdoc/>
+ public virtual CsvMode Mode { get; set; }
+
+ /// <inheritdoc/>
+ public virtual string NewLine
+ {
+ get => newLine;
+ set
+ {
+ IsNewLineSet = true;
+ newLine = value;
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual PrepareHeaderForMatch PrepareHeaderForMatch { get; set; } = ConfigurationFunctions.PrepareHeaderForMatch;
+
+ /// <inheritdoc/>
+ public virtual int ProcessFieldBufferSize { get; set; } = 1024;
+
+ /// <inheritdoc/>
+ public virtual char Quote { get; set; } = '"';
+
+ /// <inheritdoc/>
+ public virtual ReadingExceptionOccurred ReadingExceptionOccurred { get; set; } = ConfigurationFunctions.ReadingExceptionOccurred;
+
+ /// <inheritdoc/>
+ public virtual ReferenceHeaderPrefix? ReferenceHeaderPrefix { get; set; }
+
+ /// <inheritdoc/>
+ public ShouldQuote ShouldQuote { get; set; } = ConfigurationFunctions.ShouldQuote;
+
+ /// <inheritdoc/>
+ public virtual ShouldSkipRecord? ShouldSkipRecord { get; set; }
+
+ /// <inheritdoc/>
+ public virtual ShouldUseConstructorParameters ShouldUseConstructorParameters { get; set; } = ConfigurationFunctions.ShouldUseConstructorParameters;
+
+ /// <inheritdoc/>
+ public virtual TrimOptions TrimOptions { get; set; }
+
+ /// <inheritdoc/>
+ public virtual bool UseNewObjectForNullReferenceMembers { get; set; } = true;
+
+ /// <inheritdoc/>
+ public virtual char[] WhiteSpaceChars { get; set; } = new char[] { ' ' };
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvConfiguration"/> class
+ /// using the given <see cref="System.Globalization.CultureInfo"/>. Since <see cref="Delimiter"/>
+ /// uses <see cref="CultureInfo"/> for it's default, the given <see cref="System.Globalization.CultureInfo"/>
+ /// will be used instead.
+ /// </summary>
+ /// <param name="cultureInfo">The culture information.</param>
+ /// <param name="attributesType">The type that contains the configuration attributes.
+ /// This will call <see cref="ApplyAttributes(Type)"/> automatically.</param>
+ public CsvConfiguration(CultureInfo cultureInfo, Type? attributesType = null)
+ {
+ CultureInfo = cultureInfo;
+ Delimiter = cultureInfo.TextInfo.ListSeparator;
+
+ if (attributesType != null)
+ {
+ ApplyAttributes(attributesType);
+ }
+ }
+
+ /// <summary>
+ /// Validates the configuration.
+ /// </summary>
+ 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.");
+ }
+
+ /// <summary>
+ /// Applies class level attribute to configuration.
+ /// </summary>
+ /// <typeparam name="T">Type with attributes.</typeparam>
+ public CsvConfiguration ApplyAttributes<T>()
+ {
+ return ApplyAttributes(typeof(T));
+ }
+
+ /// <summary>
+ /// Applies class level attribute to configuration.
+ /// </summary>
+ /// <param name="type">Type with attributes.</param>
+ public CsvConfiguration ApplyAttributes(Type type)
+ {
+ var attributes = type.GetCustomAttributes().OfType<IClassMapper>();
+ foreach (var attribute in attributes)
+ {
+ attribute.ApplyTo(this);
+ }
+
+ return this;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/DefaultClassMap`1.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/DefaultClassMap`1.cs
new file mode 100644
index 0000000..2e1b88b
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/DefaultClassMap`1.cs
@@ -0,0 +1,15 @@
+// Copyright 2009-2022 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
+{
+ /// <summary>
+ /// A default <see cref="ClassMap{T}"/> that can be used
+ /// to create a class map dynamically.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public class DefaultClassMap<T> : ClassMap<T>
+ {
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IParserConfiguration.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IParserConfiguration.cs
new file mode 100644
index 0000000..dec8594
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IParserConfiguration.cs
@@ -0,0 +1,176 @@
+// Copyright 2009-2022 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.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Configuration used for the <see cref="IParser"/>.
+ /// </summary>
+ public interface IParserConfiguration
+ {
+ /// <summary>
+ /// Gets the culture info used to read an write CSV files.
+ /// </summary>
+ CultureInfo CultureInfo { get; }
+
+ /// <summary>
+ /// Cache fields that are created when parsing.
+ /// Default is false.
+ /// </summary>
+ bool CacheFields { get; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ string NewLine { get; }
+
+ /// <summary>
+ /// A value indicating if <see cref="NewLine"/> was set.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if <see cref="NewLine"/> was set. <c>false</c> if <see cref="NewLine"/> is the default.
+ /// </value>
+ bool IsNewLineSet { get; }
+
+ /// <summary>
+ /// The mode.
+ /// See <see cref="CsvMode"/> for more details.
+ /// </summary>
+ CsvMode Mode { get; }
+
+ /// <summary>
+ /// Gets the size of the buffer
+ /// used for parsing and writing CSV files.
+ /// Default is 0x1000.
+ /// </summary>
+ int BufferSize { get; }
+
+ /// <summary>
+ /// The size of the buffer used when processing fields.
+ /// Default is 1024.
+ /// </summary>
+ int ProcessFieldBufferSize { get; }
+
+ /// <summary>
+ /// 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 <see cref="Encoding"/> needs to be set correctly for this to be accurate.
+ /// </summary>
+ bool CountBytes { get; }
+
+ /// <summary>
+ /// Gets the encoding used when counting bytes.
+ /// </summary>
+ Encoding Encoding { get; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ BadDataFound BadDataFound { get; }
+
+ /// <summary>
+ /// Gets or sets the maximum size of a field.
+ /// Defaults to 0, indicating maximum field size is not checked.
+ /// </summary>
+ double MaxFieldSize { get; }
+
+ /// <summary>
+ /// Gets a value indicating if a line break found in a quote field should
+ /// be considered bad data. <c>true</c> to consider a line break bad data, otherwise <c>false</c>.
+ /// Defaults to false.
+ /// </summary>
+ bool LineBreakInQuotedFieldIsBadData { get; }
+
+ /// <summary>
+ /// Gets the character used to denote
+ /// a line that is commented out. Default is '#'.
+ /// </summary>
+ char Comment { get; }
+
+ /// <summary>
+ /// Gets a value indicating if comments are allowed.
+ /// <c>true</c> to allow commented out lines, otherwise <c>false</c>.
+ /// </summary>
+ bool AllowComments { get; }
+
+ /// <summary>
+ /// Gets a value indicating if blank lines
+ /// should be ignored when reading.
+ /// <c>true</c> to ignore, otherwise <c>false</c>. Default is true.
+ /// </summary>
+ bool IgnoreBlankLines { get; }
+
+ /// <summary>
+ /// Gets the character used to quote fields.
+ /// Default is '"'.
+ /// </summary>
+ char Quote { get; }
+
+ /// <summary>
+ /// The delimiter used to separate fields.
+ /// Default is <see cref="TextInfo.ListSeparator"/>.
+ /// </summary>
+ string Delimiter { get; }
+
+ /// <summary>
+ /// Detect the delimiter instead of using the delimiter from configuration.
+ /// Default is <c>false</c>.
+ /// </summary>
+ bool DetectDelimiter { get; }
+
+ /// <summary>
+ /// Gets the function that is called when <see cref="DetectDelimiter"/> is enabled.
+ /// </summary>
+ GetDelimiter GetDelimiter { get; }
+
+ /// <summary>
+ /// The possible delimiter values used when detecting the delimiter.
+ /// Default is [",", ";", "|", "\t"].
+ /// </summary>
+ string[] DetectDelimiterValues { get; }
+
+ /// <summary>
+ /// The character used to escape characters.
+ /// Default is '"'.
+ /// </summary>
+ char Escape { get; }
+
+ /// <summary>
+ /// Gets the field trimming options.
+ /// </summary>
+ TrimOptions TrimOptions { get; }
+
+ /// <summary>
+ /// Characters considered whitespace.
+ /// Used when trimming fields.
+ /// Default is [' '].
+ /// </summary>
+ char[] WhiteSpaceChars { get; }
+
+ /// <summary>
+ /// A value indicating if exception messages contain raw CSV data.
+ /// <c>true</c> if exception contain raw CSV data, otherwise <c>false</c>.
+ /// Default is <c>true</c>.
+ /// </summary>
+ bool ExceptionMessagesContainRawData { get; }
+
+ /// <summary>
+ /// Validates the configuration.
+ /// </summary>
+ void Validate();
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IReaderConfiguration.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IReaderConfiguration.cs
new file mode 100644
index 0000000..a1250e6
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IReaderConfiguration.cs
@@ -0,0 +1,111 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+using CsvHelper.TypeConversion;
+using System.Reflection;
+using System.Collections.Generic;
+using System.IO;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Configuration used for the <see cref="IReader"/>.
+ /// </summary>
+ public interface IReaderConfiguration : IParserConfiguration
+ {
+ /// <summary>
+ /// Gets a value indicating if the
+ /// CSV file has a header record.
+ /// Default is true.
+ /// </summary>
+ bool HasHeaderRecord { get; }
+
+ /// <summary>
+ /// Gets the function that is called when a header validation check is ran. The default function
+ /// will throw a <see cref="ValidationException"/> 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.
+ /// </summary>
+ HeaderValidated HeaderValidated { get; }
+
+ /// <summary>
+ /// Gets the function that is called when a missing field is found. The default function will
+ /// throw a <see cref="MissingFieldException"/>. You can supply your own function to do other things
+ /// like logging the issue instead of throwing an exception.
+ /// </summary>
+ MissingFieldFound MissingFieldFound { get; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ ReadingExceptionOccurred ReadingExceptionOccurred { get; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ PrepareHeaderForMatch PrepareHeaderForMatch { get; }
+
+ /// <summary>
+ /// Determines if constructor parameters should be used to create
+ /// the class instead of the default constructor and members.
+ /// </summary>
+ ShouldUseConstructorParameters ShouldUseConstructorParameters { get; }
+
+ /// <summary>
+ /// Chooses the constructor to use for constructor mapping.
+ /// </summary>
+ GetConstructor GetConstructor { get; }
+
+ /// <summary>
+ /// Gets the name to use for the property of the dynamic object.
+ /// </summary>
+ GetDynamicPropertyName GetDynamicPropertyName { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether references
+ /// should be ignored when auto mapping. <c>true</c> to ignore
+ /// references, otherwise <c>false</c>. Default is false.
+ /// </summary>
+ bool IgnoreReferences { get; }
+
+ /// <summary>
+ /// Gets the callback that will be called to
+ /// determine whether to skip the given record or not.
+ /// </summary>
+ ShouldSkipRecord? ShouldSkipRecord { get; }
+
+ /// <summary>
+ /// Gets a value indicating if private
+ /// member should be read from and written to.
+ /// <c>true</c> to include private member, otherwise <c>false</c>. Default is false.
+ /// </summary>
+ bool IncludePrivateMembers { get; }
+
+ /// <summary>
+ /// Gets a callback that will return the prefix for a reference header.
+ /// </summary>
+ ReferenceHeaderPrefix ReferenceHeaderPrefix { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether changes in the column
+ /// count should be detected. If true, a <see cref="BadDataException"/>
+ /// will be thrown if a different column count is detected.
+ /// </summary>
+ bool DetectColumnCountChanges { get; }
+
+ /// <summary>
+ /// Gets the member types that are used when auto mapping.
+ /// MemberTypes are flags, so you can choose more than one.
+ /// Default is Properties.
+ /// </summary>
+ MemberTypes MemberTypes { get; }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IWriterConfiguration.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IWriterConfiguration.cs
new file mode 100644
index 0000000..349c493
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IWriterConfiguration.cs
@@ -0,0 +1,168 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.IO;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Configuration used for the <see cref="IWriter"/>.
+ /// </summary>
+ public interface IWriterConfiguration
+ {
+ /// <summary>
+ /// Gets the size of the buffer
+ /// used for parsing and writing CSV files.
+ /// Default is 0x1000.
+ /// </summary>
+ int BufferSize { get; }
+
+ /// <summary>
+ /// The mode.
+ /// See <see cref="CsvMode"/> for more details.
+ /// </summary>
+ CsvMode Mode { get; }
+
+ /// <summary>
+ /// Gets the delimiter used to separate fields.
+ /// Default is ',';
+ /// </summary>
+ string Delimiter { get; }
+
+ /// <summary>
+ /// Gets the character used to quote fields.
+ /// Default is '"'.
+ /// </summary>
+ char Quote { get; }
+
+ /// <summary>
+ /// The character used to escape characters.
+ /// Default is '"'.
+ /// </summary>
+ char Escape { get; }
+
+ /// <summary>
+ /// Gets the field trimming options.
+ /// </summary>
+ TrimOptions TrimOptions { get; }
+
+ /// <summary>
+ /// Gets the injection options.
+ /// </summary>
+ InjectionOptions InjectionOptions { get; }
+
+ /// <summary>
+ /// Gets the characters that are used for injection attacks.
+ /// </summary>
+ char[] InjectionCharacters { get; }
+
+ /// <summary>
+ /// Gets the character used to escape a detected injection.
+ /// </summary>
+ char InjectionEscapeCharacter { get; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ string NewLine { get; }
+
+ /// <summary>
+ /// A value indicating if <see cref="NewLine"/> was set.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if <see cref="NewLine"/> was set. <c>false</c> if <see cref="NewLine"/> is the default.
+ /// </value>
+ bool IsNewLineSet { get; }
+
+ /// <summary>
+ /// Gets a function that is used to determine if a field should get quoted
+ /// when writing.
+ /// </summary>
+ ShouldQuote ShouldQuote { get; }
+
+ /// <summary>
+ /// Gets the culture info used to read and write CSV files.
+ /// </summary>
+ CultureInfo CultureInfo { get; }
+
+ /// <summary>
+ /// Gets a value indicating if comments are allowed.
+ /// True to allow commented out lines, otherwise false.
+ /// </summary>
+ bool AllowComments { get; }
+
+ /// <summary>
+ /// Gets the character used to denote
+ /// a line that is commented out. Default is '#'.
+ /// </summary>
+ char Comment { get; }
+
+ /// <summary>
+ /// Gets a value indicating if the
+ /// CSV file has a header record.
+ /// Default is true.
+ /// </summary>
+ bool HasHeaderRecord { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether references
+ /// should be ignored when auto mapping. True to ignore
+ /// references, otherwise false. Default is false.
+ /// </summary>
+ bool IgnoreReferences { get; }
+
+ /// <summary>
+ /// Gets a value indicating if private
+ /// member should be read from and written to.
+ /// True to include private member, otherwise false. Default is false.
+ /// </summary>
+ bool IncludePrivateMembers { get; }
+
+ /// <summary>
+ /// Gets a callback that will return the prefix for a reference header.
+ /// </summary>
+ ReferenceHeaderPrefix ReferenceHeaderPrefix { get; }
+
+ /// <summary>
+ /// Gets the member types that are used when auto mapping.
+ /// MemberTypes are flags, so you can choose more than one.
+ /// Default is Properties.
+ /// </summary>
+ MemberTypes MemberTypes { get; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ bool UseNewObjectForNullReferenceMembers { get; }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ IComparer<string> DynamicPropertySort { get; }
+
+ /// <summary>
+ /// A value indicating if exception messages contain raw CSV data.
+ /// <c>true</c> if exception contain raw CSV data, otherwise <c>false</c>.
+ /// Default is <c>true</c>.
+ /// </summary>
+ bool ExceptionMessagesContainRawData { get; }
+
+ /// <summary>
+ /// Validates the configuration.
+ /// </summary>
+ void Validate();
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/InjectionOptions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/InjectionOptions.cs
new file mode 100644
index 0000000..a7dc20e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/InjectionOptions.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Options for handling injection attacks.
+ /// </summary>
+ public enum InjectionOptions
+ {
+ /// <summary>
+ /// No injection protection.
+ /// </summary>
+ None = 0,
+ /// <summary>
+ /// Escape injection characters.
+ /// </summary>
+ Escape,
+ /// <summary>
+ /// Strip injection characters.
+ /// </summary>
+ Strip,
+ /// <summary>
+ /// Throw an exception if injection characters are detected.
+ /// </summary>
+ Exception,
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap.cs
new file mode 100644
index 0000000..006595d
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap.cs
@@ -0,0 +1,244 @@
+// Copyright 2009-2022 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.TypeConversion;
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Mapping info for a member to a CSV field.
+ /// </summary>
+ [DebuggerDisplay("Member = {Data.Member}, Names = {string.Join(\",\", Data.Names)}, Index = {Data.Index}, Ignore = {Data.Ignore}, Member = {Data.Member}, TypeConverter = {Data.TypeConverter}")]
+ public abstract class MemberMap
+ {
+ /// <summary>
+ /// Gets the member map data.
+ /// </summary>
+ public virtual MemberMapData Data { get; protected set; }
+
+ /// <summary>
+ /// Type converter options.
+ /// </summary>
+ public virtual MemberMapTypeConverterOption TypeConverterOption { get; protected set; }
+
+ /// <summary>
+ /// Creates an instance of <see cref="MemberMap"/> using the given Type and <see cref="MemberInfo"/>.
+ /// </summary>
+ /// <param name="classType">Type of the class the member being mapped belongs to.</param>
+ /// <param name="member">The member being mapped.</param>
+ public static MemberMap CreateGeneric(Type classType, MemberInfo member)
+ {
+ var memberMapType = typeof(MemberMap<,>).MakeGenericType(classType, member.MemberType());
+ var memberMap = (MemberMap)ObjectResolver.Current.Resolve(memberMapType, member);
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// When reading, is used to get the field
+ /// at the index of the name if there was a
+ /// header specified. It will look for the
+ /// first name match in the order listed.
+ /// When writing, sets the name of the
+ /// field in the header record.
+ /// The first name will be used.
+ /// </summary>
+ /// <param name="names">The possible names of the CSV field.</param>
+ public virtual MemberMap Name(params string[] names)
+ {
+ if (names == null || names.Length == 0)
+ {
+ throw new ArgumentNullException(nameof(names));
+ }
+
+ Data.Names.Clear();
+ Data.Names.AddRange(names);
+ Data.IsNameSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// When reading, is used to get the
+ /// index of the name used when there
+ /// are multiple names that are the same.
+ /// </summary>
+ /// <param name="index">The index of the name.</param>
+ public virtual MemberMap NameIndex(int index)
+ {
+ Data.NameIndex = index;
+
+ return this;
+ }
+
+ /// <summary>
+ /// When reading, is used to get the field at
+ /// the given index. When writing, the fields
+ /// will be written in the order of the field
+ /// indexes.
+ /// </summary>
+ /// <param name="index">The index of the CSV field.</param>
+ /// <param name="indexEnd">The end index used when mapping to an <see cref="IEnumerable"/> member.</param>
+ public virtual MemberMap Index(int index, int indexEnd = -1)
+ {
+ Data.Index = index;
+ Data.IsIndexSet = true;
+ Data.IndexEnd = indexEnd;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the member when reading and writing.
+ /// If this member has already been mapped as a reference
+ /// member, either by a class map, or by automapping, calling
+ /// this method will not ignore all the child members down the
+ /// tree that have already been mapped.
+ /// </summary>
+ public virtual MemberMap Ignore()
+ {
+ Data.Ignore = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the member when reading and writing.
+ /// If this member has already been mapped as a reference
+ /// member, either by a class map, or by automapping, calling
+ /// this method will not ignore all the child members down the
+ /// tree that have already been mapped.
+ /// </summary>
+ /// <param name="ignore">True to ignore, otherwise false.</param>
+ public virtual MemberMap Ignore(bool ignore)
+ {
+ Data.Ignore = ignore;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty.
+ /// </summary>
+ /// <param name="defaultValue">The default value.</param>
+ /// <param name="useOnConversionFailure">Use default on conversion failure.</param>
+ public virtual MemberMap Default(object? defaultValue, bool useOnConversionFailure = false)
+ {
+ if (defaultValue == null && Data.Member.MemberType().IsValueType)
+ {
+ throw new ArgumentException($"Member of type '{Data.Member.MemberType().FullName}' can't have a default value of null.");
+ }
+
+ if (defaultValue != null && !Data.Member.MemberType().IsAssignableFrom(defaultValue.GetType()))
+ {
+ throw new ArgumentException($"Default of type '{defaultValue.GetType().FullName}' is not assignable to '{Data.Member.MemberType().FullName}'.");
+ }
+
+ Data.Default = defaultValue;
+ Data.IsDefaultSet = true;
+ Data.UseDefaultOnConversionFailure = useOnConversionFailure;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The constant value that will be used for every record when
+ /// reading and writing. This value will always be used no matter
+ /// what other mapping configurations are specified.
+ /// </summary>
+ /// <param name="constantValue">The constant value.</param>
+ public virtual MemberMap Constant(object constantValue)
+ {
+ if (constantValue == null && Data.Member.MemberType().IsValueType)
+ {
+ throw new ArgumentException($"Member of type '{Data.Member.MemberType().FullName}' can't have a constant value of null.");
+ }
+
+ if (constantValue != null && !Data.Member.MemberType().IsAssignableFrom(constantValue.GetType()))
+ {
+ throw new ArgumentException($"Constant of type '{constantValue.GetType().FullName}' is not assignable to '{Data.Member.MemberType().FullName}'.");
+ }
+
+ Data.Constant = constantValue;
+ Data.IsConstantSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <param name="typeConverter">The TypeConverter to use.</param>
+ public virtual MemberMap TypeConverter(ITypeConverter typeConverter)
+ {
+ Data.TypeConverter = typeConverter;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <typeparam name="TConverter">The <see cref="System.Type"/> of the
+ /// <see cref="TypeConverter"/> to use.</typeparam>
+ public virtual MemberMap TypeConverter<TConverter>() where TConverter : ITypeConverter
+ {
+ TypeConverter(ObjectResolver.Current.Resolve<TConverter>());
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the member when reading if no matching field name can be found.
+ /// </summary>
+ public virtual MemberMap Optional()
+ {
+ Data.IsOptional = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies an expression to be used to validate a field when reading.
+ /// </summary>
+ /// <param name="validateExpression"></param>
+ public virtual MemberMap Validate(Validate validateExpression)
+ {
+ return Validate(validateExpression, args => $"Field '{args.Field}' is not valid.");
+ }
+
+ /// <summary>
+ /// Specifies an expression to be used to validate a field when reading along with specified exception message.
+ /// </summary>
+ /// <param name="validateExpression"></param>
+ /// <param name="validateMessageExpression"></param>
+ public virtual MemberMap Validate(Validate validateExpression, ValidateMessage validateMessageExpression)
+ {
+ var fieldParameter = Expression.Parameter(typeof(ValidateArgs), "field");
+ var validateCallExpression = Expression.Call(
+ Expression.Constant(validateExpression.Target),
+ validateExpression.Method,
+ fieldParameter
+ );
+ var messageCallExpression = Expression.Call(
+ Expression.Constant(validateMessageExpression.Target),
+ validateMessageExpression.Method,
+ fieldParameter
+ );
+
+ Data.ValidateExpression = Expression.Lambda<Validate>(validateCallExpression, fieldParameter);
+ Data.ValidateMessageExpression = Expression.Lambda<ValidateMessage>(messageCallExpression, fieldParameter);
+
+ return this;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapCollection.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapCollection.cs
new file mode 100644
index 0000000..0532544
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapCollection.cs
@@ -0,0 +1,247 @@
+// Copyright 2009-2022 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;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// A collection that holds <see cref="MemberMap"/>'s.
+ /// </summary>
+ [DebuggerDisplay("Count = {list.Count}")]
+ public class MemberMapCollection : IList<MemberMap>
+ {
+ private readonly List<MemberMap> list = new List<MemberMap>();
+ private readonly IComparer<MemberMap> comparer;
+
+ /// <summary>
+ /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <returns>
+ /// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </returns>
+ public virtual int Count => list.Count;
+
+ /// <summary>
+ /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </summary>
+ /// <returns>
+ /// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
+ /// </returns>
+ public virtual bool IsReadOnly => false;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemberMapCollection"/> class.
+ /// </summary>
+ public MemberMapCollection() : this(new MemberMapComparer()) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemberMapCollection"/> class.
+ /// </summary>
+ /// <param name="comparer">The comparer to use when sorting the member maps.</param>
+ public MemberMapCollection(IComparer<MemberMap> comparer)
+ {
+ this.comparer = comparer;
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through the collection.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
+ /// </returns>
+ /// <filterpriority>1</filterpriority>
+ public virtual IEnumerator<MemberMap> GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through a collection.
+ /// </summary>
+ /// <returns>
+ /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ /// <summary>
+ /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </exception>
+ public virtual void Add(MemberMap item)
+ {
+ list.Add(item);
+ list.Sort(comparer);
+ }
+
+ /// <summary>
+ /// Adds a range of items to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <param name="collection">The collection to add.</param>
+ public virtual void AddRange(ICollection<MemberMap> collection)
+ {
+ list.AddRange(collection);
+ list.Sort(comparer);
+ }
+
+ /// <summary>
+ /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </exception>
+ public virtual void Clear()
+ {
+ list.Clear();
+ }
+
+ /// <summary>
+ /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
+ /// </summary>
+ /// <returns>
+ /// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
+ /// </returns>
+ /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </param>
+ public virtual bool Contains(MemberMap item)
+ {
+ return list.Contains(item);
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException">The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.</exception>
+ public virtual void CopyTo(MemberMap[] array, int arrayIndex)
+ {
+ list.CopyTo(array, arrayIndex);
+ }
+
+ /// <summary>
+ /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <returns>
+ /// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </returns>
+ /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </exception>
+ public virtual bool Remove(MemberMap item)
+ {
+ return list.Remove(item);
+ }
+
+ /// <summary>
+ /// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </summary>
+ /// <returns>
+ /// The index of <paramref name="item"/> if found in the list; otherwise, -1.
+ /// </returns>
+ /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </param>
+ public virtual int IndexOf(MemberMap item)
+ {
+ return list.IndexOf(item);
+ }
+
+ /// <summary>
+ /// Inserts an item to the <see cref="T:System.Collections.Generic.IList`1"/> at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.
+ /// </param><param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public virtual void Insert(int index, MemberMap item)
+ {
+ list.Insert(index, item);
+ }
+
+ /// <summary>
+ /// Removes the <see cref="T:System.Collections.Generic.IList`1"/> item at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index of the item to remove.
+ /// </param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public virtual void RemoveAt(int index)
+ {
+ list.RemoveAt(index);
+ }
+
+ /// <summary>
+ /// Gets or sets the element at the specified index.
+ /// </summary>
+ /// <returns>
+ /// The element at the specified index.
+ /// </returns>
+ /// <param name="index">The zero-based index of the element to get or set.
+ /// </param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception><exception cref="T:System.NotSupportedException">The member is set and the <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public virtual MemberMap this[int index]
+ {
+ get { return list[index]; }
+ set { list[index] = value; }
+ }
+
+ /// <summary>
+ /// Finds the <see cref="MemberMap"/> using the given member expression.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="System.Type"/> the member is on.</typeparam>
+ /// <param name="expression">The member expression.</param>
+ /// <returns>The <see cref="MemberMap"/> for the given expression, or null if not found.</returns>
+ public virtual MemberMap? Find<T>(Expression<Func<T, object>> expression)
+ {
+ var member = ReflectionHelper.GetMember(expression);
+ return Find(member);
+ }
+
+ /// <summary>
+ /// Finds the <see cref="MemberMap"/> using the given member.
+ /// </summary>
+ /// <param name="member">The member.</param>
+ /// <returns>The <see cref="MemberMap"/> for the given expression, or null if not found.</returns>
+ public virtual MemberMap? Find(MemberInfo member)
+ {
+ var existingMap = list.SingleOrDefault(m =>
+ m.Data.Member == member ||
+ m.Data.Member != null &&
+ m.Data.Member.Name == member.Name &&
+ (
+ m.Data.Member.DeclaringType.IsAssignableFrom(member.DeclaringType) ||
+ member.DeclaringType.IsAssignableFrom(m.Data.Member.DeclaringType)
+ )
+ );
+
+ return existingMap;
+ }
+
+ /// <summary>
+ /// Adds the members from the mapping. This will recursively
+ /// traverse the mapping tree and add all members for
+ /// reference maps.
+ /// </summary>
+ /// <param name="mapping">The mapping where the members are added from.</param>
+ public virtual void AddMembers(ClassMap mapping)
+ {
+ AddRange(mapping.MemberMaps);
+ foreach (var refmap in mapping.ReferenceMaps)
+ {
+ AddMembers(refmap.Data.Mapping);
+ }
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapComparer.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapComparer.cs
new file mode 100644
index 0000000..84cdf6c
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapComparer.cs
@@ -0,0 +1,74 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Used to compare <see cref="MemberMap"/>s.
+ /// The order is by field index ascending. Any
+ /// fields that don't have an index are pushed
+ /// to the bottom.
+ /// </summary>
+ internal class MemberMapComparer : IComparer<MemberMap>
+ {
+ /// <summary>
+ /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
+ /// </summary>
+ /// <returns>
+ /// Value
+ /// Condition
+ /// Less than zero
+ /// <paramref name="x"/> is less than <paramref name="y"/>.
+ /// Zero
+ /// <paramref name="x"/> equals <paramref name="y"/>.
+ /// Greater than zero
+ /// <paramref name="x"/> is greater than <paramref name="y"/>.
+ /// </returns>
+ /// <param name="x">The first object to compare.
+ /// </param><param name="y">The second object to compare.
+ /// </param><exception cref="T:System.ArgumentException">Neither <paramref name="x"/> nor <paramref name="y"/> implements the <see cref="T:System.IComparable"/> interface.
+ /// -or-
+ /// <paramref name="x"/> and <paramref name="y"/> are of different types and neither one can handle comparisons with the other.
+ /// </exception><filterpriority>2</filterpriority>
+ public virtual int Compare( object x, object y )
+ {
+ var xMember = x as MemberMap;
+ var yMember = y as MemberMap;
+ return Compare( xMember, yMember );
+ }
+
+ /// <summary>
+ /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
+ /// </summary>
+ /// <returns>
+ /// Value
+ /// Condition
+ /// Less than zero
+ /// <paramref name="x"/> is less than <paramref name="y"/>.
+ /// Zero
+ /// <paramref name="x"/> equals <paramref name="y"/>.
+ /// Greater than zero
+ /// <paramref name="x"/> is greater than <paramref name="y"/>.
+ /// </returns>
+ /// <param name="x">The first object to compare.
+ /// </param><param name="y">The second object to compare.
+ /// </param>
+ public virtual int Compare( MemberMap x, MemberMap y )
+ {
+ if( x == null )
+ {
+ throw new ArgumentNullException( nameof( x ) );
+ }
+ if( y == null )
+ {
+ throw new ArgumentNullException( nameof( y ) );
+ }
+
+ return x.Data.Index.CompareTo( y.Data.Index );
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapData.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapData.cs
new file mode 100644
index 0000000..07d696a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapData.cs
@@ -0,0 +1,167 @@
+// Copyright 2009-2022 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.Reflection;
+using CsvHelper.TypeConversion;
+using System.Linq.Expressions;
+using System;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// The configured data for the member map.
+ /// </summary>
+ public class MemberMapData
+ {
+ /// <summary>
+ /// Gets the member type.
+ /// </summary>
+ public virtual Type Type
+ {
+ get
+ {
+ if (Member != null)
+ {
+ return Member.MemberType();
+ }
+
+ if (IsConstantSet)
+ {
+ return Constant?.GetType() ?? typeof(string);
+ }
+
+ if (IsDefaultSet)
+ {
+ return Default?.GetType() ?? typeof(string);
+ }
+
+ return typeof(string);
+ }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="MemberInfo"/> that the data
+ /// is associated with.
+ /// </summary>
+ public virtual MemberInfo? Member { get; private set; }
+
+ /// <summary>
+ /// Gets the list of column names.
+ /// </summary>
+ public virtual MemberNameCollection Names { get; } = new MemberNameCollection();
+
+ /// <summary>
+ /// Gets or sets the index of the name.
+ /// This is used if there are multiple
+ /// columns with the same names.
+ /// </summary>
+ public virtual int NameIndex { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating if the name was
+ /// explicitly set. True if it was explicitly set,
+ /// otherwise false.
+ /// </summary>
+ public virtual bool IsNameSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets the column index.
+ /// </summary>
+ public virtual int Index { get; set; } = -1;
+
+ /// <summary>
+ /// Gets or sets the index end. The Index end is used to specify a range for use
+ /// with a collection member. Index is used as the start of the range, and IndexEnd
+ /// is the end of the range.
+ /// </summary>
+ public virtual int IndexEnd { get; set; } = -1;
+
+ /// <summary>
+ /// Gets or sets a value indicating if the index was
+ /// explicitly set. True if it was explicitly set,
+ /// otherwise false.
+ /// </summary>
+ public virtual bool IsIndexSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type converter.
+ /// </summary>
+ public virtual ITypeConverter? TypeConverter { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type converter options.
+ /// </summary>
+ public virtual TypeConverterOptions TypeConverterOptions { get; set; } = new TypeConverterOptions();
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the field should be ignored.
+ /// </summary>
+ public virtual bool Ignore { get; set; }
+
+ /// <summary>
+ /// Gets or sets the default value used when a CSV field is empty.
+ /// </summary>
+ public virtual object? Default { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is default value set.
+ /// the default value was explicitly set. True if it was
+ /// explicitly set, otherwise false.
+ /// </summary>
+ public virtual bool IsDefaultSet { get; set; }
+
+ /// <summary>
+ /// Gets or setse a value indicating if the default value should be used when
+ /// a type conversion failure happens. <c>true</c> to use the default, otherwise
+ /// <c>false</c>.
+ /// </summary>
+ public virtual bool UseDefaultOnConversionFailure { get; set; }
+
+ /// <summary>
+ /// Gets or sets the constant value used for every record.
+ /// </summary>
+ public virtual object? Constant { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating if a constant was explicitly set.
+ /// </summary>
+ public virtual bool IsConstantSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets the expression used to convert data in the
+ /// row to the member.
+ /// </summary>
+ public virtual Expression ReadingConvertExpression { get; set; }
+
+ /// <summary>
+ /// Gets or sets the expression to be used to convert the object
+ /// to a field.
+ /// </summary>
+ public virtual Expression WritingConvertExpression { get; set; }
+
+ /// <summary>
+ /// Gets or sets the expression use to validate a field.
+ /// </summary>
+ public virtual Expression ValidateExpression { get; set; }
+
+ /// <summary>
+ /// Gets or sets the expression used to get the validation message when validation fails.
+ /// </summary>
+ public virtual Expression ValidateMessageExpression { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating if a field is optional.
+ /// </summary>
+ public virtual bool IsOptional { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemberMapData"/> class.
+ /// </summary>
+ /// <param name="member">The member.</param>
+ public MemberMapData(MemberInfo? member)
+ {
+ Member = member;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapTypeConverterOption.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapTypeConverterOption.cs
new file mode 100644
index 0000000..bafad45
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapTypeConverterOption.cs
@@ -0,0 +1,167 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Sets type converter options on a member map.
+ /// </summary>
+ public class MemberMapTypeConverterOption
+ {
+ private readonly MemberMap memberMap;
+
+ /// <summary>
+ /// Creates a new instance using the given <see cref="MemberMap"/>.
+ /// </summary>
+ /// <param name="memberMap">The member map the options are being applied to.</param>
+ public MemberMapTypeConverterOption(MemberMap memberMap)
+ {
+ this.memberMap = memberMap;
+ }
+
+ /// <summary>
+ /// The <see cref="CultureInfo"/> used when type converting.
+ /// This will override the global <see cref="CsvConfiguration.CultureInfo"/>
+ /// setting.
+ /// </summary>
+ /// <param name="cultureInfo">The culture info.</param>
+ public virtual MemberMap CultureInfo(CultureInfo cultureInfo)
+ {
+ memberMap.Data.TypeConverterOptions.CultureInfo = cultureInfo;
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// The <see cref="DateTimeStyles"/> to use when type converting.
+ /// This is used when doing any <see cref="DateTime"/> conversions.
+ /// </summary>
+ /// <param name="dateTimeStyle">The date time style.</param>
+ public virtual MemberMap DateTimeStyles(DateTimeStyles dateTimeStyle)
+ {
+ memberMap.Data.TypeConverterOptions.DateTimeStyle = dateTimeStyle;
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// The <see cref="TimeSpanStyles"/> to use when type converting.
+ /// This is used when doing <see cref="TimeSpan"/> converting.
+ /// </summary>
+ /// <param name="timeSpanStyles">The time span styles.</param>
+ public virtual MemberMap TimespanStyles(TimeSpanStyles timeSpanStyles)
+ {
+ memberMap.Data.TypeConverterOptions.TimeSpanStyle = timeSpanStyles;
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// The <see cref="NumberStyles"/> to use when type converting.
+ /// This is used when doing any number conversions.
+ /// </summary>
+ /// <param name="numberStyle"></param>
+ public virtual MemberMap NumberStyles(NumberStyles numberStyle)
+ {
+ memberMap.Data.TypeConverterOptions.NumberStyles = numberStyle;
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// The string format to be used when type converting.
+ /// </summary>
+ /// <param name="formats">The format.</param>
+ public virtual MemberMap Format(params string[] formats)
+ {
+ memberMap.Data.TypeConverterOptions.Formats = formats;
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// The <see cref="UriKind"/> to use when converting.
+ /// This is used when doing <see cref="Uri"/> conversions.
+ /// </summary>
+ /// <param name="uriKind">Kind of the URI.</param>
+ public virtual MemberMap UriKind(UriKind uriKind)
+ {
+ memberMap.Data.TypeConverterOptions.UriKind = uriKind;
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// The string values used to represent a boolean when converting.
+ /// </summary>
+ /// <param name="isTrue">A value indicating whether true values or false values are being set.</param>
+ /// <param name="clearValues">A value indication if the current values should be cleared before adding the new ones.</param>
+ /// <param name="booleanValues">The string boolean values.</param>
+ public virtual MemberMap BooleanValues(bool isTrue, bool clearValues = true, params string[] booleanValues)
+ {
+ if (isTrue)
+ {
+ if (clearValues)
+ {
+ memberMap.Data.TypeConverterOptions.BooleanTrueValues.Clear();
+ }
+
+ memberMap.Data.TypeConverterOptions.BooleanTrueValues.AddRange(booleanValues);
+ }
+ else
+ {
+ if (clearValues)
+ {
+ memberMap.Data.TypeConverterOptions.BooleanFalseValues.Clear();
+ }
+
+ memberMap.Data.TypeConverterOptions.BooleanFalseValues.AddRange(booleanValues);
+ }
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// The string values used to represent null when converting.
+ /// </summary>
+ /// <param name="nullValues">The values that represent null.</param>
+ /// <returns></returns>
+ public virtual MemberMap NullValues(params string[] nullValues)
+ {
+ return NullValues(true, nullValues);
+ }
+
+ /// <summary>
+ /// The string values used to represent null when converting.
+ /// </summary>
+ /// <param name="clearValues">A value indication if the current values should be cleared before adding the new ones.</param>
+ /// <param name="nullValues">The values that represent null.</param>
+ /// <returns></returns>
+ public virtual MemberMap NullValues(bool clearValues, params string[] nullValues)
+ {
+ if (clearValues)
+ {
+ memberMap.Data.TypeConverterOptions.NullValues.Clear();
+ }
+
+ memberMap.Data.TypeConverterOptions.NullValues.AddRange(nullValues);
+
+ return memberMap;
+ }
+
+ /// <summary>
+ /// Ignore case when parsing enums.
+ /// </summary>
+ /// <param name="ignoreCase"><c>true</c> to ignore case, otherwise <c>false</c>.</param>
+ public virtual MemberMap EnumIgnoreCase(bool ignoreCase = true)
+ {
+ memberMap.Data.TypeConverterOptions.EnumIgnoreCase = ignoreCase;
+
+ return memberMap;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap`1.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap`1.cs
new file mode 100644
index 0000000..590f05a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap`1.cs
@@ -0,0 +1,270 @@
+// Copyright 2009-2022 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.TypeConversion;
+using System;
+using System.Collections;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Mapping info for a member to a CSV field.
+ /// </summary>
+ public class MemberMap<TClass, TMember> : MemberMap
+ {
+ /// <summary>
+ /// Creates a new <see cref="MemberMap"/> instance using the specified member.
+ /// </summary>
+ public MemberMap(MemberInfo? member)
+ {
+ TypeConverterOption = new MemberMapTypeConverterOption(this);
+
+ Data = new MemberMapData(member);
+ }
+
+ /// <summary>
+ /// When reading, is used to get the field
+ /// at the index of the name if there was a
+ /// header specified. It will look for the
+ /// first name match in the order listed.
+ /// When writing, sets the name of the
+ /// field in the header record.
+ /// The first name will be used.
+ /// </summary>
+ /// <param name="names">The possible names of the CSV field.</param>
+ public new virtual MemberMap<TClass, TMember> Name(params string[] names)
+ {
+ if (names == null || names.Length == 0)
+ {
+ throw new ArgumentNullException(nameof(names));
+ }
+
+ Data.Names.Clear();
+ Data.Names.AddRange(names);
+ Data.IsNameSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// When reading, is used to get the
+ /// index of the name used when there
+ /// are multiple names that are the same.
+ /// </summary>
+ /// <param name="index">The index of the name.</param>
+ public new virtual MemberMap<TClass, TMember> NameIndex(int index)
+ {
+ Data.NameIndex = index;
+
+ return this;
+ }
+
+ /// <summary>
+ /// When reading, is used to get the field at
+ /// the given index. When writing, the fields
+ /// will be written in the order of the field
+ /// indexes.
+ /// </summary>
+ /// <param name="index">The index of the CSV field.</param>
+ /// <param name="indexEnd">The end index used when mapping to an <see cref="IEnumerable"/> member.</param>
+ public new virtual MemberMap<TClass, TMember> Index(int index, int indexEnd = -1)
+ {
+ Data.Index = index;
+ Data.IsIndexSet = true;
+ Data.IndexEnd = indexEnd;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the member when reading and writing.
+ /// If this member has already been mapped as a reference
+ /// member, either by a class map, or by automapping, calling
+ /// this method will not ignore all the child members down the
+ /// tree that have already been mapped.
+ /// </summary>
+ public new virtual MemberMap<TClass, TMember> Ignore()
+ {
+ Data.Ignore = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the member when reading and writing.
+ /// If this member has already been mapped as a reference
+ /// member, either by a class map, or by automapping, calling
+ /// this method will not ignore all the child members down the
+ /// tree that have already been mapped.
+ /// </summary>
+ /// <param name="ignore">True to ignore, otherwise false.</param>
+ public new virtual MemberMap<TClass, TMember> Ignore(bool ignore)
+ {
+ Data.Ignore = ignore;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty.
+ /// </summary>
+ /// <param name="defaultValue">The default value.</param>
+ /// <param name="useOnConversionFailure">Use default on conversion failure.</param>
+ public virtual MemberMap<TClass, TMember> Default(TMember defaultValue, bool useOnConversionFailure = false)
+ {
+ Data.Default = defaultValue;
+ Data.IsDefaultSet = true;
+ Data.UseDefaultOnConversionFailure = useOnConversionFailure;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty. This value is not type checked
+ /// and will use a <see cref="ITypeConverter"/> to convert
+ /// the field. This could potentially have runtime errors.
+ /// </summary>
+ /// <param name="defaultValue">The default value.</param>
+ /// <param name="useOnConversionFailure">Use default on conversion failure.</param>
+ public virtual MemberMap<TClass, TMember> Default(string defaultValue, bool useOnConversionFailure = false)
+ {
+ Data.Default = defaultValue;
+ Data.IsDefaultSet = true;
+ Data.UseDefaultOnConversionFailure = useOnConversionFailure;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The constant value that will be used for every record when
+ /// reading and writing. This value will always be used no matter
+ /// what other mapping configurations are specified.
+ /// </summary>
+ /// <param name="constantValue">The constant value.</param>
+ public virtual MemberMap<TClass, TMember> Constant(TMember? constantValue)
+ {
+ Data.Constant = constantValue;
+ Data.IsConstantSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <param name="typeConverter">The TypeConverter to use.</param>
+ public new virtual MemberMap<TClass, TMember> TypeConverter(ITypeConverter typeConverter)
+ {
+ Data.TypeConverter = typeConverter;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the member to and from a CSV field.
+ /// </summary>
+ /// <typeparam name="TConverter">The <see cref="System.Type"/> of the
+ /// <see cref="TypeConverter"/> to use.</typeparam>
+ public new virtual MemberMap<TClass, TMember> TypeConverter<TConverter>() where TConverter : ITypeConverter
+ {
+ TypeConverter(ObjectResolver.Current.Resolve<TConverter>());
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies an expression to be used to convert data in the
+ /// row to the member.
+ /// </summary>
+ /// <param name="convertFromStringFunction">The convert expression.</param>
+ public virtual MemberMap<TClass, TMember> Convert(ConvertFromString<TMember> convertFromStringFunction)
+ {
+ var instance = convertFromStringFunction.Target != null ? Expression.Constant(convertFromStringFunction.Target) : null;
+ var fieldParameter = Expression.Parameter(typeof(ConvertFromStringArgs), "args");
+ var methodExpression = Expression.Call
+ (
+ instance,
+ convertFromStringFunction.Method,
+ fieldParameter
+ );
+ var lambdaExpression = Expression.Lambda<ConvertFromString<TMember>>(methodExpression, fieldParameter);
+
+ Data.ReadingConvertExpression = lambdaExpression;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies an expression to be used to convert the object
+ /// to a field.
+ /// </summary>
+ /// <param name="convertToStringFunction">The convert expression.</param>
+ public virtual MemberMap<TClass, TMember> Convert(ConvertToString<TClass> convertToStringFunction)
+ {
+ var instance = convertToStringFunction.Target != null ? Expression.Constant(convertToStringFunction.Target) : null;
+ var fieldParameter = Expression.Parameter(typeof(ConvertToStringArgs<TClass>), "args");
+ var methodExpression = Expression.Call
+ (
+ instance,
+ convertToStringFunction.Method,
+ fieldParameter
+ );
+ var lambdaExpression = Expression.Lambda<ConvertToString<TClass>>(methodExpression, fieldParameter);
+
+ Data.WritingConvertExpression = lambdaExpression;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the member when reading if no matching field name can be found.
+ /// </summary>
+ public new virtual MemberMap<TClass, TMember> Optional()
+ {
+ Data.IsOptional = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies an expression to be used to validate a field when reading.
+ /// </summary>
+ /// <param name="validateExpression"></param>
+ public new virtual MemberMap<TClass, TMember> Validate(Validate validateExpression)
+ {
+ return Validate(validateExpression, args => $"Field '{args.Field}' is not valid.");
+ }
+
+ /// <summary>
+ /// Specifies an expression to be used to validate a field when reading along with specified exception message.
+ /// </summary>
+ /// <param name="validateExpression"></param>
+ /// <param name="validateMessageExpression"></param>
+ public new virtual MemberMap<TClass, TMember> Validate(Validate validateExpression, ValidateMessage validateMessageExpression)
+ {
+ var fieldParameter = Expression.Parameter(typeof(ValidateArgs), "args");
+ var validateCallExpression = Expression.Call(
+ Expression.Constant(validateExpression.Target),
+ validateExpression.Method,
+ fieldParameter
+ );
+ var messageCallExpression = Expression.Call(
+ Expression.Constant(validateMessageExpression.Target),
+ validateMessageExpression.Method,
+ fieldParameter
+ );
+
+ Data.ValidateExpression = Expression.Lambda<Validate>(validateCallExpression, fieldParameter);
+ Data.ValidateMessageExpression = Expression.Lambda<ValidateMessage>(messageCallExpression, fieldParameter);
+
+ return this;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberNameCollection.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberNameCollection.cs
new file mode 100644
index 0000000..fb9db4a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberNameCollection.cs
@@ -0,0 +1,98 @@
+// Copyright 2009-2022 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.Collections;
+using System.Collections.Generic;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// A collection that holds member names.
+ /// </summary>
+ public class MemberNameCollection : IEnumerable<string>
+ {
+ private readonly List<string> names = new List<string>();
+
+ /// <summary>
+ /// Gets the name at the given index. If a prefix is set,
+ /// it will be prepended to the name.
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ public string this[int index]
+ {
+ get { return Prefix + names[index]; }
+ set { names[index] = value; }
+ }
+
+ /// <summary>
+ /// Gets the prefix to use for each name.
+ /// </summary>
+ public string Prefix { get; set; }
+
+ /// <summary>
+ /// Gets the raw list of names without
+ /// the prefix being prepended.
+ /// </summary>
+ public List<string> Names => names;
+
+ /// <summary>
+ /// Gets the count.
+ /// </summary>
+ public int Count => names.Count;
+
+ /// <summary>
+ /// Adds the given name to the collection.
+ /// </summary>
+ /// <param name="name">The name to add.</param>
+ public void Add(string name)
+ {
+ names.Add(name);
+ }
+
+ /// <summary>
+ /// Clears all names from the collection.
+ /// </summary>
+ public void Clear()
+ {
+ names.Clear();
+ }
+
+ /// <summary>
+ /// Adds a range of names to the collection.
+ /// </summary>
+ /// <param name="names">The range to add.</param>
+ public void AddRange(IEnumerable<string> names)
+ {
+ this.names.AddRange(names);
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through the collection.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
+ /// </returns>
+ /// <filterpriority>1</filterpriority>
+ public IEnumerator<string> GetEnumerator()
+ {
+ for (var i = 0; i < names.Count; i++)
+ {
+ yield return this[i];
+ }
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through a collection.
+ /// </summary>
+ /// <returns>
+ /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return names.GetEnumerator();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMap.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMap.cs
new file mode 100644
index 0000000..66dca90
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMap.cs
@@ -0,0 +1,68 @@
+// Copyright 2009-2022 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;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Mapping info for a reference member mapping to a class.
+ /// </summary>
+ [DebuggerDisplay("Member = {Data.Member}, Prefix = {Data.Prefix}")]
+ public class MemberReferenceMap
+ {
+ private readonly MemberReferenceMapData data;
+
+ /// <summary>
+ /// Gets the member reference map data.
+ /// </summary>
+ public MemberReferenceMapData Data => data;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemberReferenceMap"/> class.
+ /// </summary>
+ /// <param name="member">The member.</param>
+ /// <param name="mapping">The <see cref="ClassMap"/> to use for the reference map.</param>
+ public MemberReferenceMap(MemberInfo member, ClassMap mapping)
+ {
+ if (mapping == null)
+ {
+ throw new ArgumentNullException(nameof(mapping));
+ }
+
+ data = new MemberReferenceMapData(member, mapping);
+ }
+
+ /// <summary>
+ /// Appends a prefix to the header of each field of the reference member.
+ /// </summary>
+ /// <param name="prefix">The prefix to be prepended to headers of each reference member.</param>
+ /// <param name="inherit">Inherit parent prefixes.</param>
+ /// <returns>The current <see cref="MemberReferenceMap" /></returns>
+ public MemberReferenceMap Prefix(string? prefix = null, bool inherit = false)
+ {
+ if (string.IsNullOrEmpty(prefix))
+ {
+ prefix = data.Member.Name + ".";
+ }
+
+ data.Inherit = inherit;
+ data.Prefix = prefix;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Get the largest index for the
+ /// members and references.
+ /// </summary>
+ /// <returns>The max index.</returns>
+ internal int GetMaxIndex()
+ {
+ return data.Mapping.GetMaxIndex();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapCollection.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapCollection.cs
new file mode 100644
index 0000000..c8745ed
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapCollection.cs
@@ -0,0 +1,164 @@
+// Copyright 2009-2022 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;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// A collection that holds <see cref="MemberReferenceMap"/>'s.
+ /// </summary>
+ [DebuggerDisplay("Count = {list.Count}")]
+ public class MemberReferenceMapCollection : IList<MemberReferenceMap>
+ {
+ private readonly List<MemberReferenceMap> list = new List<MemberReferenceMap>();
+
+ /// <summary>Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
+ /// <returns>The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1" />.</returns>
+ public virtual int Count => list.Count;
+
+ /// <summary>Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</summary>
+ /// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only; otherwise, false.</returns>
+ public virtual bool IsReadOnly => false;
+
+ /// <summary>Gets or sets the element at the specified index.</summary>
+ /// <returns>The element at the specified index.</returns>
+ /// <param name="index">The zero-based index of the element to get or set.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index" /> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1" />.</exception>
+ /// <exception cref="T:System.NotSupportedException">The member is set and the <see cref="T:System.Collections.Generic.IList`1" /> is read-only.</exception>
+ public virtual MemberReferenceMap this[int index]
+ {
+ get => list[index];
+ set => list[index] = value;
+ }
+
+ /// <summary>Returns an enumerator that iterates through the collection.</summary>
+ /// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
+ /// <filterpriority>1</filterpriority>
+ public virtual IEnumerator<MemberReferenceMap> GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+
+ /// <summary>Returns an enumerator that iterates through a collection.</summary>
+ /// <returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
+ /// <filterpriority>2</filterpriority>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ /// <summary>Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
+ /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
+ /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</exception>
+ public virtual void Add(MemberReferenceMap item)
+ {
+ list.Add(item);
+ }
+
+ /// <summary>Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
+ /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only. </exception>
+ public virtual void Clear()
+ {
+ list.Clear();
+ }
+
+ /// <summary>Determines whether the <see cref="T:System.Collections.Generic.ICollection`1" /> contains a specific value.</summary>
+ /// <returns>true if <paramref name="item" /> is found in the <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false.</returns>
+ /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
+ public virtual bool Contains(MemberReferenceMap item)
+ {
+ return list.Contains(item);
+ }
+
+ /// <summary>Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1" /> to an <see cref="T:System.Array" />, starting at a particular <see cref="T:System.Array" /> index.</summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array" /> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1" />. The <see cref="T:System.Array" /> must have zero-based indexing.</param>
+ /// <param name="arrayIndex">The zero-based index in <paramref name="array" /> at which copying begins.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// <paramref name="array" /> is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="arrayIndex" /> is less than 0.</exception>
+ /// <exception cref="T:System.ArgumentException">The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1" /> is greater than the available space from <paramref name="arrayIndex" /> to the end of the destination <paramref name="array" />.</exception>
+ public virtual void CopyTo(MemberReferenceMap[] array, int arrayIndex)
+ {
+ list.CopyTo(array, arrayIndex);
+ }
+
+ /// <summary>Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
+ /// <returns>true if <paramref name="item" /> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false. This method also returns false if <paramref name="item" /> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1" />.</returns>
+ /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
+ /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</exception>
+ public virtual bool Remove(MemberReferenceMap item)
+ {
+ return list.Remove(item);
+ }
+
+ /// <summary>Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1" />.</summary>
+ /// <returns>The index of <paramref name="item" /> if found in the list; otherwise, -1.</returns>
+ /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1" />.</param>
+ public virtual int IndexOf(MemberReferenceMap item)
+ {
+ return list.IndexOf(item);
+ }
+
+ /// <summary>Inserts an item to the <see cref="T:System.Collections.Generic.IList`1" /> at the specified index.</summary>
+ /// <param name="index">The zero-based index at which <paramref name="item" /> should be inserted.</param>
+ /// <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1" />.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index" /> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1" />.</exception>
+ /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1" /> is read-only.</exception>
+ public virtual void Insert(int index, MemberReferenceMap item)
+ {
+ list.Insert(index, item);
+ }
+
+ /// <summary>Removes the <see cref="T:System.Collections.Generic.IList`1" /> item at the specified index.</summary>
+ /// <param name="index">The zero-based index of the item to remove.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index" /> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1" />.</exception>
+ /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1" /> is read-only.</exception>
+ public virtual void RemoveAt(int index)
+ {
+ list.RemoveAt(index);
+ }
+
+ /// <summary>
+ /// Finds the <see cref="MemberReferenceMap"/> using the given member expression.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="System.Type"/> the member is on.</typeparam>
+ /// <param name="expression">The member expression.</param>
+ /// <returns>The <see cref="MemberReferenceMap"/> for the given expression, or null if not found.</returns>
+ public virtual MemberReferenceMap? Find<T>(Expression<Func<T, object>> expression)
+ {
+ var member = ReflectionHelper.GetMember(expression);
+ return Find(member);
+ }
+
+ /// <summary>
+ /// Finds the <see cref="MemberReferenceMap"/> using the given member.
+ /// </summary>
+ /// <param name="member">The member.</param>
+ /// <returns>The <see cref="MemberReferenceMap"/> for the given expression, or null if not found.</returns>
+ public virtual MemberReferenceMap? Find(MemberInfo member)
+ {
+ var existingMap = list.SingleOrDefault(m =>
+ m.Data.Member == member ||
+ m.Data.Member.Name == member.Name &&
+ (
+ m.Data.Member.DeclaringType.IsAssignableFrom(member.DeclaringType) ||
+ member.DeclaringType.IsAssignableFrom(m.Data.Member.DeclaringType)
+ )
+ );
+
+ return existingMap;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapData.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapData.cs
new file mode 100644
index 0000000..0726a35
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapData.cs
@@ -0,0 +1,68 @@
+// Copyright 2009-2022 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.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// The configuration data for the reference map.
+ /// </summary>
+ public class MemberReferenceMapData
+ {
+ private string prefix;
+
+ /// <summary>
+ /// Gets or sets the header prefix to use.
+ /// </summary>
+ public virtual string Prefix
+ {
+ get { return prefix; }
+ set
+ {
+ prefix = value;
+ foreach (var memberMap in Mapping.MemberMaps)
+ {
+ memberMap.Data.Names.Prefix = value;
+ }
+
+ if (Inherit)
+ {
+ foreach (var memberRef in Mapping.ReferenceMaps)
+ {
+ memberRef.Data.Prefix = memberRef.Data.Prefix == null ? value : string.Concat(value, memberRef.Data.Prefix);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating if a prefix should inherit its parent.
+ /// <c>true</c> to inherit, otherwise <c>false</c>.
+ /// </summary>
+ public virtual bool Inherit { get; set; }
+
+ /// <summary>
+ /// Gets the <see cref="MemberInfo"/> that the data
+ /// is associated with.
+ /// </summary>
+ public virtual MemberInfo Member { get; private set; }
+
+ /// <summary>
+ /// Gets the mapping this is a reference for.
+ /// </summary>
+ public ClassMap Mapping { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemberReferenceMapData"/> class.
+ /// </summary>
+ /// <param name="member">The member.</param>
+ /// <param name="mapping">The mapping this is a reference for.</param>
+ public MemberReferenceMapData(MemberInfo member, ClassMap mapping)
+ {
+ Member = member;
+ Mapping = mapping;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberTypes.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberTypes.cs
new file mode 100644
index 0000000..378524f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberTypes.cs
@@ -0,0 +1,32 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Flags for the type of members that
+ /// can be used for auto mapping.
+ /// </summary>
+ [Flags]
+ public enum MemberTypes
+ {
+ /// <summary>
+ /// No members. This is not a valid value
+ /// and will cause an exception if used.
+ /// </summary>
+ None = 0,
+
+ /// <summary>
+ /// Properties on a class.
+ /// </summary>
+ Properties = 1,
+
+ /// <summary>
+ /// Fields on a class.
+ /// </summary>
+ Fields = 2
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMap.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMap.cs
new file mode 100644
index 0000000..991cc8b
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMap.cs
@@ -0,0 +1,212 @@
+// Copyright 2009-2022 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.TypeConversion;
+using System;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Mapping for a constructor parameter.
+ /// This may contain value type data, a constructor type map,
+ /// or a reference map, depending on the type of the parameter.
+ /// </summary>
+ [DebuggerDisplay("Data = {Data}")]
+ public class ParameterMap
+ {
+ /// <summary>
+ /// Gets the parameter map data.
+ /// </summary>
+ public virtual ParameterMapData Data { get; protected set; }
+
+ /// <summary>
+ /// Type converter options.
+ /// </summary>
+ public virtual ParameterMapTypeConverterOption TypeConverterOption { get; protected set; }
+
+ /// <summary>
+ /// Gets or sets the map for a constructor type.
+ /// </summary>
+ public virtual ClassMap ConstructorTypeMap { get; set; }
+
+ /// <summary>
+ /// Gets or sets the map for a reference type.
+ /// </summary>
+ public virtual ParameterReferenceMap ReferenceMap { get; set; }
+
+ /// <summary>
+ /// Creates an instance of <see cref="ParameterMap"/> using
+ /// the given information.
+ /// </summary>
+ /// <param name="parameter">The parameter being mapped.</param>
+ public ParameterMap(ParameterInfo parameter)
+ {
+ TypeConverterOption = new ParameterMapTypeConverterOption(this);
+
+ Data = new ParameterMapData(parameter);
+ }
+
+ /// <summary>
+ /// When reading, is used to get the field
+ /// at the index of the name if there was a
+ /// header specified. It will look for the
+ /// first name match in the order listed.
+ /// When writing, sets the name of the
+ /// field in the header record.
+ /// The first name will be used.
+ /// </summary>
+ /// <param name="names">The possible names of the CSV field.</param>
+ public virtual ParameterMap Name(params string[] names)
+ {
+ if (names == null || names.Length == 0)
+ {
+ throw new ArgumentNullException(nameof(names));
+ }
+
+ Data.Names.Clear();
+ Data.Names.AddRange(names);
+ Data.IsNameSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// When reading, is used to get the
+ /// index of the name used when there
+ /// are multiple names that are the same.
+ /// </summary>
+ /// <param name="index">The index of the name.</param>
+ public virtual ParameterMap NameIndex(int index)
+ {
+ Data.NameIndex = index;
+
+ return this;
+ }
+
+ /// <summary>
+ /// When reading, is used to get the field at
+ /// the given index. When writing, the fields
+ /// will be written in the order of the field
+ /// indexes.
+ /// </summary>
+ /// <param name="index">The index of the CSV field.</param>
+ public virtual ParameterMap Index(int index)
+ {
+ Data.Index = index;
+ Data.IsIndexSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the parameter when reading and writing.
+ /// </summary>
+ public virtual ParameterMap Ignore()
+ {
+ Data.Ignore = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Ignore the parameter when reading and writing.
+ /// </summary>
+ /// <param name="ignore">True to ignore, otherwise false.</param>
+ public virtual ParameterMap Ignore(bool ignore)
+ {
+ Data.Ignore = ignore;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The default value that will be used when reading when
+ /// the CSV field is empty.
+ /// </summary>
+ /// <param name="defaultValue">The default value.</param>
+ public virtual ParameterMap Default(object? defaultValue)
+ {
+ if (defaultValue == null && Data.Parameter.ParameterType.IsValueType)
+ {
+ throw new ArgumentException($"Parameter of type '{Data.Parameter.ParameterType.FullName}' can't have a default value of null.");
+ }
+
+ if (defaultValue != null && defaultValue.GetType() != Data.Parameter.ParameterType)
+ {
+ throw new ArgumentException($"Default of type '{defaultValue.GetType().FullName}' does not match parameter of type '{Data.Parameter.ParameterType.FullName}'.");
+ }
+
+ Data.Default = defaultValue;
+ Data.IsDefaultSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The constant value that will be used for every record when
+ /// reading and writing. This value will always be used no matter
+ /// what other mapping configurations are specified.
+ /// </summary>
+ /// <param name="constantValue">The constant value.</param>
+ public virtual ParameterMap Constant(object? constantValue)
+ {
+ if (constantValue == null && Data.Parameter.ParameterType.IsValueType)
+ {
+ throw new ArgumentException($"Parameter of type '{Data.Parameter.ParameterType.FullName}' can't have a constant value of null.");
+ }
+
+ if (constantValue != null && constantValue.GetType() != Data.Parameter.ParameterType)
+ {
+ throw new ArgumentException($"Constant of type '{constantValue.GetType().FullName}' does not match parameter of type '{Data.Parameter.ParameterType.FullName}'.");
+ }
+
+ Data.Constant = constantValue;
+ Data.IsConstantSet = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// The field is optional.
+ /// </summary>
+ public virtual ParameterMap Optional()
+ {
+ Data.IsOptional = true;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the parameter to and from a CSV field.
+ /// </summary>
+ /// <param name="typeConverter">The TypeConverter to use.</param>
+ public virtual ParameterMap TypeConverter(ITypeConverter typeConverter)
+ {
+ Data.TypeConverter = typeConverter;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Specifies the <see cref="TypeConverter"/> to use
+ /// when converting the parameter to and from a CSV field.
+ /// </summary>
+ /// <typeparam name="TConverter">The <see cref="System.Type"/> of the
+ /// <see cref="TypeConverter"/> to use.</typeparam>
+ public virtual ParameterMap TypeConverter<TConverter>() where TConverter : ITypeConverter
+ {
+ TypeConverter(ObjectResolver.Current.Resolve<TConverter>());
+
+ return this;
+ }
+
+ internal int GetMaxIndex()
+ {
+ return ReferenceMap?.GetMaxIndex() ?? Data.Index;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapData.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapData.cs
new file mode 100644
index 0000000..a83edbe
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapData.cs
@@ -0,0 +1,106 @@
+// Copyright 2009-2022 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.TypeConversion;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// The constructor parameter data for the map.
+ /// </summary>
+ [DebuggerDisplay("Index = {Index}, Names = {string.Join(\", \", Names)}, Parameter = {Parameter}")]
+ public class ParameterMapData
+ {
+ /// <summary>
+ /// Gets the <see cref="ParameterInfo"/> that the data
+ /// is associated with.
+ /// </summary>
+ public virtual ParameterInfo Parameter { get; private set; }
+
+ /// <summary>
+ /// Gets the list of column names.
+ /// </summary>
+ public virtual MemberNameCollection Names { get; } = new MemberNameCollection();
+
+ /// <summary>
+ /// Gets or sets the index of the name.
+ /// This is used if there are multiple
+ /// columns with the same names.
+ /// </summary>
+ public virtual int NameIndex { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating if the name was
+ /// explicitly set. True if it was explicitly set,
+ /// otherwise false.
+ /// </summary>
+ public virtual bool IsNameSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets the column index.
+ /// </summary>
+ public virtual int Index { get; set; } = -1;
+
+ /// <summary>
+ /// Gets or sets a value indicating if the index was
+ /// explicitly set. True if it was explicitly set,
+ /// otherwise false.
+ /// </summary>
+ public virtual bool IsIndexSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type converter.
+ /// </summary>
+ public virtual ITypeConverter TypeConverter { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type converter options.
+ /// </summary>
+ public virtual TypeConverterOptions TypeConverterOptions { get; set; } = new TypeConverterOptions();
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the field should be ignored.
+ /// </summary>
+ public virtual bool Ignore { get; set; }
+
+ /// <summary>
+ /// Gets or sets the default value used when a CSV field is empty.
+ /// </summary>
+ public virtual object? Default { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is default value set.
+ /// the default value was explicitly set. True if it was
+ /// explicitly set, otherwise false.
+ /// </summary>
+ public virtual bool IsDefaultSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets the constant value used for every record.
+ /// </summary>
+ public virtual object? Constant { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating if a constant was explicitly set.
+ /// </summary>
+ public virtual bool IsConstantSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating if a field is optional.
+ /// </summary>
+ public virtual bool IsOptional { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ParameterMapData"/> class.
+ /// </summary>
+ /// <param name="parameter">The constructor parameter.</param>
+ public ParameterMapData(ParameterInfo parameter)
+ {
+ Parameter = parameter;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapTypeConverterOption.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapTypeConverterOption.cs
new file mode 100644
index 0000000..4b3d82a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapTypeConverterOption.cs
@@ -0,0 +1,160 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Sets type converter options on a parameter map.
+ /// </summary>
+ public class ParameterMapTypeConverterOption
+ {
+ private readonly ParameterMap parameterMap;
+
+ /// <summary>
+ /// Creates a new instance using the given <see cref="ParameterMap"/>.
+ /// </summary>
+ /// <param name="parameterMap">The member map the options are being applied to.</param>
+ public ParameterMapTypeConverterOption(ParameterMap parameterMap)
+ {
+ this.parameterMap = parameterMap;
+ }
+
+ /// <summary>
+ /// The <see cref="CultureInfo"/> used when type converting.
+ /// This will override the global <see cref="CsvConfiguration.CultureInfo"/>
+ /// setting.
+ /// </summary>
+ /// <param name="cultureInfo">The culture info.</param>
+ public virtual ParameterMap CultureInfo(CultureInfo cultureInfo)
+ {
+ parameterMap.Data.TypeConverterOptions.CultureInfo = cultureInfo;
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// The <see cref="DateTimeStyles"/> to use when type converting.
+ /// This is used when doing any <see cref="DateTime"/> conversions.
+ /// </summary>
+ /// <param name="dateTimeStyle">The date time style.</param>
+ public virtual ParameterMap DateTimeStyles(DateTimeStyles dateTimeStyle)
+ {
+ parameterMap.Data.TypeConverterOptions.DateTimeStyle = dateTimeStyle;
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// The <see cref="TimeSpanStyles"/> to use when type converting.
+ /// This is used when doing <see cref="TimeSpan"/> converting.
+ /// </summary>
+ /// <param name="timeSpanStyles">The time span styles.</param>
+ public virtual ParameterMap TimespanStyles(TimeSpanStyles timeSpanStyles)
+ {
+ parameterMap.Data.TypeConverterOptions.TimeSpanStyle = timeSpanStyles;
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// The <see cref="NumberStyles"/> to use when type converting.
+ /// This is used when doing any number conversions.
+ /// </summary>
+ /// <param name="numberStyle"></param>
+ public virtual ParameterMap NumberStyles(NumberStyles numberStyle)
+ {
+ parameterMap.Data.TypeConverterOptions.NumberStyles = numberStyle;
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// The string format to be used when type converting.
+ /// </summary>
+ /// <param name="formats">The format.</param>
+ public virtual ParameterMap Format(params string[] formats)
+ {
+ parameterMap.Data.TypeConverterOptions.Formats = formats;
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// The <see cref="UriKind"/> to use when converting.
+ /// This is used when doing <see cref="Uri"/> conversions.
+ /// </summary>
+ /// <param name="uriKind">Kind of the URI.</param>
+ public virtual ParameterMap UriKind(UriKind uriKind)
+ {
+ parameterMap.Data.TypeConverterOptions.UriKind = uriKind;
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// The string values used to represent a boolean when converting.
+ /// </summary>
+ /// <param name="isTrue">A value indicating whether true values or false values are being set.</param>
+ /// <param name="clearValues">A value indication if the current values should be cleared before adding the new ones.</param>
+ /// <param name="booleanValues">The string boolean values.</param>
+ public virtual ParameterMap BooleanValues(bool isTrue, bool clearValues = true, params string[] booleanValues)
+ {
+ if (isTrue)
+ {
+ if (clearValues)
+ {
+ parameterMap.Data.TypeConverterOptions.BooleanTrueValues.Clear();
+ }
+
+ parameterMap.Data.TypeConverterOptions.BooleanTrueValues.AddRange(booleanValues);
+ }
+ else
+ {
+ if (clearValues)
+ {
+ parameterMap.Data.TypeConverterOptions.BooleanFalseValues.Clear();
+ }
+
+ parameterMap.Data.TypeConverterOptions.BooleanFalseValues.AddRange(booleanValues);
+ }
+
+ return parameterMap;
+ }
+
+ /// <summary>
+ /// The string values used to represent null when converting.
+ /// </summary>
+ /// <param name="nullValues">The values that represent null.</param>
+ /// <returns></returns>
+ public virtual ParameterMap NullValues(params string[] nullValues)
+ {
+ return NullValues(true, nullValues);
+ }
+
+ /// <summary>
+ /// The string values used to represent null when converting.
+ /// </summary>
+ /// <param name="clearValues">A value indication if the current values should be cleared before adding the new ones.</param>
+ /// <param name="nullValues">The values that represent null.</param>
+ /// <returns></returns>
+ public virtual ParameterMap NullValues(bool clearValues, params string[] nullValues)
+ {
+ if (clearValues)
+ {
+ parameterMap.Data.TypeConverterOptions.NullValues.Clear();
+ }
+
+ parameterMap.Data.TypeConverterOptions.NullValues.AddRange(nullValues);
+
+ return parameterMap;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMap.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMap.cs
new file mode 100644
index 0000000..7e9a5f3
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMap.cs
@@ -0,0 +1,66 @@
+// Copyright 2009-2022 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;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Mapping info for a reference parameter mapping to a class.
+ /// </summary>
+ public class ParameterReferenceMap
+ {
+ private readonly ParameterReferenceMapData data;
+
+ /// <summary>
+ /// Gets the parameter reference map data.
+ /// </summary>
+ public ParameterReferenceMapData Data => data;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ParameterReferenceMap"/> class.
+ /// </summary>
+ /// <param name="parameter">The parameter.</param>
+ /// <param name="mapping">The <see cref="ClassMap"/> to use for the reference map.</param>
+ public ParameterReferenceMap(ParameterInfo parameter, ClassMap mapping)
+ {
+ if (mapping == null)
+ {
+ throw new ArgumentNullException(nameof(mapping));
+ }
+
+ data = new ParameterReferenceMapData(parameter, mapping);
+ }
+
+ /// <summary>
+ /// Appends a prefix to the header of each field of the reference parameter.
+ /// </summary>
+ /// <param name="prefix">The prefix to be prepended to headers of each reference parameter.</param>
+ /// <param name="inherit">Inherit parent prefixes.</param>
+ /// <returns>The current <see cref="ParameterReferenceMap" /></returns>
+ public ParameterReferenceMap Prefix(string prefix = null, bool inherit = false)
+ {
+ if (string.IsNullOrEmpty(prefix))
+ {
+ prefix = data.Parameter.Name + ".";
+ }
+
+ data.Inherit = inherit;
+ data.Prefix = prefix;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Get the largest index for the
+ /// members and references.
+ /// </summary>
+ /// <returns>The max index.</returns>
+ internal int GetMaxIndex()
+ {
+ return data.Mapping.GetMaxIndex();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMapData.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMapData.cs
new file mode 100644
index 0000000..ab2a28d
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMapData.cs
@@ -0,0 +1,70 @@
+// Copyright 2009-2022 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.Diagnostics;
+using System.Reflection;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// The configuration data for the reference map.
+ /// </summary>
+ [DebuggerDisplay( "Prefix = {Prefix}, Parameter = {Parameter}" )]
+ public class ParameterReferenceMapData
+ {
+ private string prefix;
+
+ /// <summary>
+ /// Gets or sets the header prefix to use.
+ /// </summary>
+ public virtual string Prefix
+ {
+ get { return prefix; }
+ set
+ {
+ prefix = value;
+ foreach( var memberMap in Mapping.MemberMaps )
+ {
+ memberMap.Data.Names.Prefix = value;
+ }
+
+ if (Inherit)
+ {
+ foreach (var memberRef in Mapping.ReferenceMaps)
+ {
+ memberRef.Data.Prefix = memberRef.Data.Prefix == null ? value : string.Concat(value, memberRef.Data.Prefix);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating if a prefix should inherit its parent.
+ /// <c>true</c> to inherit, otherwise <c>false</c>.
+ /// </summary>
+ public virtual bool Inherit { get; set; }
+
+ /// <summary>
+ /// Gets the <see cref="ParameterInfo"/> that the data
+ /// is associated with.
+ /// </summary>
+ public virtual ParameterInfo Parameter { get; private set; }
+
+ /// <summary>
+ /// Gets the mapping this is a reference for.
+ /// </summary>
+ public ClassMap Mapping { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ParameterReferenceMapData"/> class.
+ /// </summary>
+ /// <param name="parameter">The parameter.</param>
+ /// <param name="mapping">The mapping this is a reference for.</param>
+ public ParameterReferenceMapData( ParameterInfo parameter, ClassMap mapping )
+ {
+ Parameter = parameter;
+ Mapping = mapping;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/TrimOptions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/TrimOptions.cs
new file mode 100644
index 0000000..5555c92
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/TrimOptions.cs
@@ -0,0 +1,30 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Configuration
+{
+ /// <summary>
+ /// Options for trimming of fields.
+ /// </summary>
+ [Flags]
+ public enum TrimOptions
+ {
+ /// <summary>
+ /// No trimming.
+ /// </summary>
+ None = 0,
+
+ /// <summary>
+ /// Trims the whitespace around a field.
+ /// </summary>
+ Trim = 1,
+
+ /// <summary>
+ /// Trims the whitespace inside of quotes around a field.
+ /// </summary>
+ InsideQuotes = 2
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvContext.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvContext.cs
new file mode 100644
index 0000000..27c5d00
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvContext.cs
@@ -0,0 +1,202 @@
+// Copyright 2009-2022 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;
+using CsvHelper.TypeConversion;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Share state for CsvHelper.
+ /// </summary>
+ public class CsvContext
+ {
+ /// <summary>
+ /// Gets or sets the <see cref="TypeConverterOptionsCache"/>.
+ /// </summary>
+ public virtual TypeConverterOptionsCache TypeConverterOptionsCache { get; set; } = new TypeConverterOptionsCache();
+
+ /// <summary>
+ /// Gets or sets the <see cref="TypeConverterOptionsCache"/>.
+ /// </summary>
+ public virtual TypeConverterCache TypeConverterCache { get; set; } = new TypeConverterCache();
+
+ /// <summary>
+ /// The configured <see cref="ClassMap"/>s.
+ /// </summary>
+ public virtual ClassMapCollection Maps { get; private set; }
+
+ /// <summary>
+ /// Gets the parser.
+ /// </summary>
+ public IParser Parser { get; private set; }
+
+ /// <summary>
+ /// Gets the reader.
+ /// </summary>
+ public IReader Reader { get; internal set; }
+
+ /// <summary>
+ /// Gets the writer.
+ /// </summary>
+ public IWriter Writer { get; internal set; }
+
+ /// <summary>
+ /// Gets the configuration.
+ /// </summary>
+ public CsvConfiguration Configuration { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvContext"/> class.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public CsvContext(IReader reader)
+ {
+ Reader = reader;
+ Parser = reader.Parser;
+ Configuration = reader.Configuration as CsvConfiguration ?? throw new InvalidOperationException($"{nameof(IReader)}.{nameof(IReader.Configuration)} must be of type {nameof(CsvConfiguration)} to be used in the context.");
+ Maps = new ClassMapCollection(this);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvContext"/> class.
+ /// </summary>
+ /// <param name="parser">The parser.</param>
+ public CsvContext(IParser parser)
+ {
+ Parser = parser;
+ Configuration = parser.Configuration as CsvConfiguration ?? throw new InvalidOperationException($"{nameof(IParser)}.{nameof(IParser.Configuration)} must be of type {nameof(CsvConfiguration)} to be used in the context.");
+ Maps = new ClassMapCollection(this);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvContext"/> class.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public CsvContext(IWriter writer)
+ {
+ Writer = writer;
+ Configuration = writer.Configuration as CsvConfiguration ?? throw new InvalidOperationException($"{nameof(IWriter)}.{nameof(IWriter.Configuration)} must be of type {nameof(CsvConfiguration)} to be used in the context.");
+ Maps = new ClassMapCollection(this);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvContext"/> class.
+ /// </summary>
+ /// <param name="configuration">The configuration.</param>
+ public CsvContext(CsvConfiguration configuration)
+ {
+ Configuration = configuration;
+ Maps = new ClassMapCollection(this);
+ }
+
+ /// <summary>
+ /// Use a <see cref="ClassMap{T}" /> to configure mappings.
+ /// When using a class map, no members are mapped by default.
+ /// Only member specified in the mapping are used.
+ /// </summary>
+ /// <typeparam name="TMap">The type of mapping class to use.</typeparam>
+ public virtual TMap RegisterClassMap<TMap>() where TMap : ClassMap
+ {
+ var map = ObjectResolver.Current.Resolve<TMap>();
+ RegisterClassMap(map);
+
+ return map;
+ }
+
+ /// <summary>
+ /// Use a <see cref="ClassMap{T}" /> to configure mappings.
+ /// When using a class map, no members are mapped by default.
+ /// Only members specified in the mapping are used.
+ /// </summary>
+ /// <param name="classMapType">The type of mapping class to use.</param>
+ public virtual ClassMap RegisterClassMap(Type classMapType)
+ {
+ if (!typeof(ClassMap).IsAssignableFrom(classMapType))
+ {
+ throw new ArgumentException("The class map type must inherit from CsvClassMap.");
+ }
+
+ var map = (ClassMap)ObjectResolver.Current.Resolve(classMapType);
+ RegisterClassMap(map);
+
+ return map;
+ }
+
+ /// <summary>
+ /// Registers the class map.
+ /// </summary>
+ /// <param name="map">The class map to register.</param>
+ public virtual void RegisterClassMap(ClassMap map)
+ {
+ if (map.MemberMaps.Count == 0 && map.ReferenceMaps.Count == 0 && map.ParameterMaps.Count == 0)
+ {
+ throw new ConfigurationException("No mappings were specified in the CsvClassMap.");
+ }
+
+ Maps.Add(map);
+ }
+
+ /// <summary>
+ /// Unregisters the class map.
+ /// </summary>
+ /// <typeparam name="TMap">The map type to unregister.</typeparam>
+ public virtual void UnregisterClassMap<TMap>()
+ where TMap : ClassMap
+ {
+ UnregisterClassMap(typeof(TMap));
+ }
+
+ /// <summary>
+ /// Unregisters the class map.
+ /// </summary>
+ /// <param name="classMapType">The map type to unregister.</param>
+ public virtual void UnregisterClassMap(Type classMapType)
+ {
+ Maps.Remove(classMapType);
+ }
+
+ /// <summary>
+ /// Unregisters all class maps.
+ /// </summary>
+ public virtual void UnregisterClassMap()
+ {
+ Maps.Clear();
+ }
+
+ /// <summary>
+ /// Generates a <see cref="ClassMap"/> for the type.
+ /// </summary>
+ /// <typeparam name="T">The type to generate the map for.</typeparam>
+ /// <returns>The generate map.</returns>
+ public virtual ClassMap<T> AutoMap<T>()
+ {
+ var map = ObjectResolver.Current.Resolve<DefaultClassMap<T>>();
+ map.AutoMap(this);
+ Maps.Add(map);
+
+ return map;
+ }
+
+ /// <summary>
+ /// Generates a <see cref="ClassMap"/> for the type.
+ /// </summary>
+ /// <param name="type">The type to generate for the map.</param>
+ /// <returns>The generate map.</returns>
+ public virtual ClassMap AutoMap(Type type)
+ {
+ var mapType = typeof(DefaultClassMap<>).MakeGenericType(type);
+ var map = (ClassMap)ObjectResolver.Current.Resolve(mapType);
+ map.AutoMap(this);
+ Maps.Add(map);
+
+ return map;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvDataReader.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvDataReader.cs
new file mode 100644
index 0000000..0e67cf9
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvDataReader.cs
@@ -0,0 +1,387 @@
+// Copyright 2009-2022 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;
+using System.Data;
+using System.Globalization;
+using System.Linq;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Provides a means of reading a CSV file forward-only by using CsvReader.
+ /// </summary>
+ /// <seealso cref="System.Data.IDataReader" />
+ public class CsvDataReader : IDataReader
+ {
+ private readonly CsvReader csv;
+ private readonly DataTable schemaTable;
+ private bool skipNextRead;
+
+ /// <inheritdoc />
+ public object this[int i]
+ {
+ get
+ {
+ return csv[i] ?? string.Empty;
+ }
+ }
+
+ /// <inheritdoc />
+ public object this[string name]
+ {
+ get
+ {
+ return csv[name] ?? string.Empty;
+ }
+ }
+
+ /// <inheritdoc />
+ public int Depth
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ /// <inheritdoc />
+ public bool IsClosed { get; private set; }
+
+ /// <inheritdoc />
+ public int RecordsAffected
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ /// <inheritdoc />
+ public int FieldCount
+ {
+ get
+ {
+ return csv?.Parser.Count ?? 0;
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvDataReader"/> class.
+ /// </summary>
+ /// <param name="csv">The CSV.</param>
+ /// <param name="schemaTable">The DataTable representing the file schema.</param>
+ public CsvDataReader(CsvReader csv, DataTable? schemaTable = null)
+ {
+ this.csv = csv;
+
+ csv.Read();
+
+ if (csv.Configuration.HasHeaderRecord)
+ {
+ csv.ReadHeader();
+ }
+ else
+ {
+ skipNextRead = true;
+ }
+
+ this.schemaTable = schemaTable ?? GetSchemaTable();
+ }
+
+ /// <inheritdoc />
+ public void Close()
+ {
+ Dispose();
+ }
+
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ csv.Dispose();
+ IsClosed = true;
+ }
+
+ /// <inheritdoc />
+ public bool GetBoolean(int i)
+ {
+ return csv.GetField<bool>(i);
+ }
+
+ /// <inheritdoc />
+ public byte GetByte(int i)
+ {
+ return csv.GetField<byte>(i);
+ }
+
+ /// <inheritdoc />
+ public long GetBytes(int i, long fieldOffset, byte[]? buffer, int bufferoffset, int length)
+ {
+ var bytes = csv.GetField<byte[]>(i);
+
+ buffer ??= new byte[bytes.Length];
+
+ Array.Copy(bytes, fieldOffset, buffer, bufferoffset, length);
+
+ return bytes.Length;
+ }
+
+ /// <inheritdoc />
+ public char GetChar(int i)
+ {
+ return csv.GetField<char>(i);
+ }
+
+ /// <inheritdoc />
+ public long GetChars(int i, long fieldoffset, char[]? buffer, int bufferoffset, int length)
+ {
+ var chars = csv.GetField(i).ToCharArray();
+
+ buffer ??= new char[chars.Length];
+
+ Array.Copy(chars, fieldoffset, buffer, bufferoffset, length);
+
+ return chars.Length;
+ }
+
+ /// <inheritdoc />
+ public IDataReader GetData(int i)
+ {
+ throw new NotSupportedException();
+ }
+
+ /// <inheritdoc />
+ public string GetDataTypeName(int i)
+ {
+ if (i >= schemaTable.Rows.Count)
+ {
+ throw new IndexOutOfRangeException($"SchemaTable does not contain a definition for field '{i}'.");
+ }
+
+ var row = schemaTable.Rows[i];
+ var field = row["DataType"] as Type;
+
+ if (field == null)
+ {
+ throw new InvalidOperationException($"SchemaTable does not contain a 'DataType' of type 'Type' for field '{i}'.");
+ }
+
+ return field.Name;
+ }
+
+ /// <inheritdoc />
+ public DateTime GetDateTime(int i)
+ {
+ return csv.GetField<DateTime>(i);
+ }
+
+ /// <inheritdoc />
+ public decimal GetDecimal(int i)
+ {
+ return csv.GetField<decimal>(i);
+ }
+
+ /// <inheritdoc />
+ public double GetDouble(int i)
+ {
+ return csv.GetField<double>(i);
+ }
+
+ /// <inheritdoc />
+ public Type GetFieldType(int i)
+ {
+ return typeof(string);
+ }
+
+ /// <inheritdoc />
+ public float GetFloat(int i)
+ {
+ return csv.GetField<float>(i);
+ }
+
+ /// <inheritdoc />
+ public Guid GetGuid(int i)
+ {
+ return csv.GetField<Guid>(i);
+ }
+
+ /// <inheritdoc />
+ public short GetInt16(int i)
+ {
+ return csv.GetField<short>(i);
+ }
+
+ /// <inheritdoc />
+ public int GetInt32(int i)
+ {
+ return csv.GetField<int>(i);
+ }
+
+ /// <inheritdoc />
+ public long GetInt64(int i)
+ {
+ return csv.GetField<long>(i);
+ }
+
+ /// <inheritdoc />
+ public string GetName(int i)
+ {
+ return csv.Configuration.HasHeaderRecord
+ ? csv.HeaderRecord[i]
+ : string.Empty;
+ }
+
+ /// <inheritdoc />
+ public int GetOrdinal(string name)
+ {
+ var index = csv.GetFieldIndex(name, isTryGet: true);
+ if (index >= 0)
+ {
+ return index;
+ }
+
+ var args = new PrepareHeaderForMatchArgs(name, 0);
+ var namePrepared = csv.Configuration.PrepareHeaderForMatch(args);
+
+ var headerRecord = csv.HeaderRecord;
+ for (var i = 0; i < headerRecord.Length; i++)
+ {
+ args = new PrepareHeaderForMatchArgs(headerRecord[i], i);
+ var headerPrepared = csv.Configuration.PrepareHeaderForMatch(args);
+ if (csv.Configuration.CultureInfo.CompareInfo.Compare(namePrepared, headerPrepared, CompareOptions.IgnoreCase) == 0)
+ {
+ return i;
+ }
+ }
+
+ throw new IndexOutOfRangeException($"Field with name '{name}' and prepared name '{namePrepared}' was not found.");
+ }
+
+ /// <inheritdoc />
+ public DataTable GetSchemaTable()
+ {
+ if (schemaTable != null)
+ {
+ return schemaTable;
+ }
+
+ // https://docs.microsoft.com/en-us/dotnet/api/system.data.datatablereader.getschematable?view=netframework-4.7.2
+ var dt = new DataTable("SchemaTable");
+ dt.Columns.Add("AllowDBNull", typeof(bool));
+ dt.Columns.Add("AutoIncrementSeed", typeof(long));
+ dt.Columns.Add("AutoIncrementStep", typeof(long));
+ dt.Columns.Add("BaseCatalogName");
+ dt.Columns.Add("BaseColumnName");
+ dt.Columns.Add("BaseColumnNamespace");
+ dt.Columns.Add("BaseSchemaName");
+ dt.Columns.Add("BaseTableName");
+ dt.Columns.Add("BaseTableNamespace");
+ dt.Columns.Add("ColumnName");
+ dt.Columns.Add("ColumnMapping", typeof(MappingType));
+ dt.Columns.Add("ColumnOrdinal", typeof(int));
+ dt.Columns.Add("ColumnSize", typeof(int));
+ dt.Columns.Add("DataType", typeof(Type));
+ dt.Columns.Add("DefaultValue", typeof(object));
+ dt.Columns.Add("Expression");
+ dt.Columns.Add("IsAutoIncrement", typeof(bool));
+ dt.Columns.Add("IsKey", typeof(bool));
+ dt.Columns.Add("IsLong", typeof(bool));
+ dt.Columns.Add("IsReadOnly", typeof(bool));
+ dt.Columns.Add("IsRowVersion", typeof(bool));
+ dt.Columns.Add("IsUnique", typeof(bool));
+ dt.Columns.Add("NumericPrecision", typeof(short));
+ dt.Columns.Add("NumericScale", typeof(short));
+ dt.Columns.Add("ProviderType", typeof(int));
+
+ if (csv.Configuration.HasHeaderRecord)
+ {
+ var header = csv.HeaderRecord;
+
+ for (var i = 0; i < header.Length; i++)
+ {
+ var row = dt.NewRow();
+ row["AllowDBNull"] = true;
+ row["AutoIncrementSeed"] = DBNull.Value;
+ row["AutoIncrementStep"] = DBNull.Value;
+ row["BaseCatalogName"] = null;
+ row["BaseColumnName"] = header[i];
+ row["BaseColumnNamespace"] = null;
+ row["BaseSchemaName"] = null;
+ row["BaseTableName"] = null;
+ row["BaseTableNamespace"] = null;
+ row["ColumnName"] = header[i];
+ row["ColumnMapping"] = MappingType.Element;
+ row["ColumnOrdinal"] = i;
+ row["ColumnSize"] = int.MaxValue;
+ row["DataType"] = typeof(string);
+ row["DefaultValue"] = null;
+ row["Expression"] = null;
+ row["IsAutoIncrement"] = false;
+ row["IsKey"] = false;
+ row["IsLong"] = false;
+ row["IsReadOnly"] = true;
+ row["IsRowVersion"] = false;
+ row["IsUnique"] = false;
+ row["NumericPrecision"] = DBNull.Value;
+ row["NumericScale"] = DBNull.Value;
+ row["ProviderType"] = DbType.String;
+
+ dt.Rows.Add(row);
+ }
+ }
+
+ return dt;
+ }
+
+ /// <inheritdoc />
+ public string GetString(int i)
+ {
+ return csv.GetField(i) ?? string.Empty;
+ }
+
+ /// <inheritdoc />
+ public object GetValue(int i)
+ {
+ return IsDBNull(i) ? DBNull.Value : (csv.GetField(i) ?? string.Empty);
+ }
+
+ /// <inheritdoc />
+ public int GetValues(object[] values)
+ {
+ for (var i = 0; i < values.Length; i++)
+ {
+ values[i] = IsDBNull(i) ? DBNull.Value : (csv.GetField(i) ?? string.Empty);
+ }
+
+ return csv.Parser.Count;
+ }
+
+ /// <inheritdoc />
+ public bool IsDBNull(int i)
+ {
+ var field = csv.GetField(i);
+ var nullValues = csv.Context.TypeConverterOptionsCache.GetOptions<string>().NullValues;
+
+ return field == null || nullValues.Contains(field);
+ }
+
+ /// <inheritdoc />
+ public bool NextResult()
+ {
+ return false;
+ }
+
+ /// <inheritdoc />
+ public bool Read()
+ {
+ if (skipNextRead)
+ {
+ skipNextRead = false;
+ return true;
+ }
+
+ return csv.Read();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.csproj b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.csproj
new file mode 100644
index 0000000..28dcaad
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.csproj
@@ -0,0 +1,92 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <!-- Assembly -->
+ <AssemblyTitle>CsvHelper</AssemblyTitle>
+ <Description>A library for reading and writing CSV files. Extremely fast, flexible, and easy to use. Supports reading and writing of custom class objects.</Description>
+ <Copyright>Copyright © 2009-2022 Josh Close</Copyright>
+ <Authors>Josh Close</Authors>
+
+ <!-- Build -->
+ <AssemblyName>CsvHelper</AssemblyName>
+ <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net47;net462</TargetFrameworks>
+ <!--<TargetFrameworks>net60</TargetFrameworks>-->
+ <LangVersion>latest</LangVersion>
+ <RootNamespace>CsvHelper</RootNamespace>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
+ <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
+ <!--<Nullable>enable</Nullable>
+ <WarningsAsErrors>nullable</WarningsAsErrors>-->
+
+ <!-- Sign -->
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>CsvHelper.snk</AssemblyOriginatorKeyFile>
+ <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
+
+ <!-- NuGet -->
+ <PackageId>CsvHelper</PackageId>
+ <PackageTags>csv;csvhelper;comma;separated;value;delimited</PackageTags>
+ <PackageIcon>Icon.png</PackageIcon>
+ <PackageIconUrl>https://raw.github.com/JoshClose/CsvHelper/master/logo/Comma-Small.png</PackageIconUrl>
+ <PackageProjectUrl>https://joshclose.github.io/CsvHelper/</PackageProjectUrl>
+ <PackageReleaseNotes>https://joshclose.github.io/CsvHelper/change-log</PackageReleaseNotes>
+ <PackageLicenseExpression>MS-PL OR Apache-2.0</PackageLicenseExpression>
+ <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
+ <PublishRepositoryUrl>true</PublishRepositoryUrl>
+ <RepositoryUrl>https://github.com/JoshClose/CsvHelper</RepositoryUrl>
+ <RepositoryType>git</RepositoryType>
+ <IncludeSymbols>true</IncludeSymbols>
+ <SymbolPackageFormat>snupkg</SymbolPackageFormat>
+ <EmbedUntrackedSources>true</EmbedUntrackedSources>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <None Remove="*.ncrunchproject" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <None Include="Icon.png" Pack="true" PackagePath="\" />
+ </ItemGroup>
+
+ <!-- .NET 4.5 -->
+ <ItemGroup Condition="'$(TargetFramework)' == 'net45'">
+ <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
+ <PackageReference Include="System.Memory" Version="4.5.0" />
+ <PackageReference Include="System.ValueTuple" Version="4.3.0" />
+ </ItemGroup>
+
+ <!-- .NET 4.7 -->
+ <ItemGroup Condition="'$(TargetFramework)' == 'net47'">
+ <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0" />
+ <PackageReference Include="Microsoft.Bcl.HashCode" Version="1.0.0" />
+ <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
+ <PackageReference Include="System.Memory" Version="4.5.0" />
+ <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
+ </ItemGroup>
+
+ <!-- .NET Standard 2.0 -->
+ <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
+ <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0" />
+ <PackageReference Include="Microsoft.Bcl.HashCode" Version="1.0.0" />
+ <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
+ <PackageReference Include="System.Memory" Version="4.5.0" />
+ <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
+ </ItemGroup>
+
+ <!-- .NET Standard 2.1 -->
+ <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
+ <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.SourceLink.GitHub" Version="[1.0.0]">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
+ </ItemGroup>
+
+</Project> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net45.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net45.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net45.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net47.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net47.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net47.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net5.0.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net5.0.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net5.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net50.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net50.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net50.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net6.0.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net6.0.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net6.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net60.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net60.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net60.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.0.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.0.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.1.v3.ncrunchproject b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.1.v3.ncrunchproject
new file mode 100644
index 0000000..9d694dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.1.v3.ncrunchproject
@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+ <Settings>
+ <PreventSigningOfAssembly>True</PreventSigningOfAssembly>
+ </Settings>
+</ProjectConfiguration> \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.snk b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.snk
new file mode 100644
index 0000000..8c9bfaf
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.snk
Binary files differ
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelperException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelperException.cs
new file mode 100644
index 0000000..10e0cdc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelperException.cs
@@ -0,0 +1,144 @@
+// Copyright 2009-2022 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;
+using System;
+using System.Text;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents errors that occur in CsvHelper.
+ /// </summary>
+ [Serializable]
+ public class CsvHelperException : Exception
+ {
+ [NonSerialized]
+ private readonly CsvContext context;
+
+ /// <summary>
+ /// Gets the context.
+ /// </summary>
+ public CsvContext Context => context;
+
+ /// <summary>
+ /// Initializes a new instance of the CsvHelperException class.
+ /// </summary>
+ internal protected CsvHelperException() : base() { }
+
+ /// <summary>
+ /// Initializes a new instance of the CsvHelperException class.
+ /// </summary>
+ /// <param name="message">The message that describes the error.</param>
+ internal protected CsvHelperException(string message) : base(message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the CsvHelperException class.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ internal protected CsvHelperException(string message, Exception innerException) : base(message, innerException) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvHelperException"/> class.
+ /// </summary>
+ public CsvHelperException(CsvContext context)
+ {
+ this.context = context;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvHelperException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public CsvHelperException(CsvContext context, string message) : base(AddDetails(message, context))
+ {
+ this.context = context;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvHelperException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public CsvHelperException(CsvContext context, string message, Exception innerException) : base(AddDetails(message, context), innerException)
+ {
+ this.context = context;
+ }
+
+ private static string AddDetails(string message, CsvContext context)
+ {
+ var indent = new string(' ', 3);
+
+ var details = new StringBuilder();
+
+ if (context.Reader != null)
+ {
+ details.AppendLine($"{nameof(IReader)} state:");
+ details.AppendLine($"{indent}{nameof(IReader.ColumnCount)}: {context.Reader.ColumnCount}");
+ details.AppendLine($"{indent}{nameof(IReader.CurrentIndex)}: {context.Reader.CurrentIndex}");
+ try
+ {
+ var record = new StringBuilder();
+ if (context.Reader.HeaderRecord != null)
+ {
+ record.Append("[\"");
+ record.Append(string.Join("\",\"", context.Reader.HeaderRecord));
+ record.Append("\"]");
+ }
+
+ details.AppendLine($"{indent}{nameof(IReader.HeaderRecord)}:{Environment.NewLine}{record}");
+ }
+ catch { }
+ }
+
+ if (context.Parser != null)
+ {
+ details.AppendLine($"{nameof(IParser)} state:");
+ details.AppendLine($"{indent}{nameof(IParser.ByteCount)}: {context.Parser.ByteCount}");
+ details.AppendLine($"{indent}{nameof(IParser.CharCount)}: {context.Parser.CharCount}");
+ details.AppendLine($"{indent}{nameof(IParser.Row)}: {context.Parser.Row}");
+ details.AppendLine($"{indent}{nameof(IParser.RawRow)}: {context.Parser.RawRow}");
+ details.AppendLine($"{indent}{nameof(IParser.Count)}: {context.Parser.Count}");
+
+ try
+ {
+ var rawRecord = context.Configuration.ExceptionMessagesContainRawData
+ ? context.Parser.RawRecord
+ : $"Hidden because {nameof(IParserConfiguration.ExceptionMessagesContainRawData)} is false.";
+ details.AppendLine($"{indent}{nameof(IParser.RawRecord)}:{Environment.NewLine}{rawRecord}");
+ }
+ catch { }
+ }
+
+ if (context.Writer != null)
+ {
+ details.AppendLine($"{nameof(IWriter)} state:");
+ details.AppendLine($"{indent}{nameof(IWriter.Row)}: {context.Writer.Row}");
+ details.AppendLine($"{indent}{nameof(IWriter.Index)}: {context.Writer.Index}");
+
+ var record = new StringBuilder();
+ if (context.Writer.HeaderRecord != null)
+ {
+ record.Append("[");
+ if (context.Writer.HeaderRecord.Length > 0)
+ {
+ record.Append("\"");
+ record.Append(string.Join("\",\"", context.Writer.HeaderRecord));
+ record.Append("\"");
+ }
+ record.Append("]");
+ }
+ details.AppendLine($"{indent}{nameof(IWriter.HeaderRecord)}:{Environment.NewLine}{context.Writer.Row}");
+ }
+
+ return $"{message}{Environment.NewLine}{details}";
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvMode.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvMode.cs
new file mode 100644
index 0000000..af11bab
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvMode.cs
@@ -0,0 +1,43 @@
+// Copyright 2009-2022 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;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Mode to use when parsing and writing.
+ /// </summary>
+ public enum CsvMode
+ {
+ /// <summary>
+ /// Uses RFC 4180 format (default).
+ /// If a field contains a <see cref="CsvConfiguration.Delimiter"/> or <see cref="CsvConfiguration.NewLine"/>,
+ /// it is wrapped in <see cref="CsvConfiguration.Quote"/>s.
+ /// If quoted field contains a <see cref="CsvConfiguration.Quote"/>, it is preceded by <see cref="CsvConfiguration.Escape"/>.
+ /// </summary>
+ RFC4180 = 0,
+
+ /// <summary>
+ /// Uses escapes.
+ /// If a field contains a <see cref="CsvConfiguration.Delimiter"/>, <see cref="CsvConfiguration.NewLine"/>,
+ /// or <see cref="CsvConfiguration.Escape"/>, it is preceded by <see cref="CsvConfiguration.Escape"/>.
+ /// Newline defaults to \n.
+ /// </summary>
+ Escape,
+
+ /// <summary>
+ /// Doesn't use quotes or escapes.
+ /// This will ignore quoting and escape characters. This means a field cannot contain a
+ /// <see cref="CsvConfiguration.Delimiter"/>, <see cref="CsvConfiguration.Quote"/>, or
+ /// <see cref="CsvConfiguration.NewLine"/>, as they cannot be escaped.
+ /// </summary>
+ NoEscape
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvParser.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvParser.cs
new file mode 100644
index 0000000..6d0db59
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvParser.cs
@@ -0,0 +1,1194 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Delegates;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Parses a CSV file.
+ /// </summary>
+ public class CsvParser : IParser, IDisposable
+ {
+ private readonly IParserConfiguration configuration;
+ private readonly FieldCache fieldCache = new FieldCache();
+ private readonly TextReader reader;
+ private readonly char quote;
+ private readonly char escape;
+ private readonly bool countBytes;
+ private readonly Encoding encoding;
+ private readonly bool ignoreBlankLines;
+ private readonly char comment;
+ private readonly bool allowComments;
+ private readonly BadDataFound badDataFound;
+ private readonly bool lineBreakInQuotedFieldIsBadData;
+ private readonly TrimOptions trimOptions;
+ private readonly char[] whiteSpaceChars;
+ private readonly bool leaveOpen;
+ private readonly CsvMode mode;
+ private readonly string newLine;
+ private readonly char newLineFirstChar;
+ private readonly bool isNewLineSet;
+ private readonly bool cacheFields;
+ private readonly string[] delimiterValues;
+ private readonly bool detectDelimiter;
+ private readonly double maxFieldSize;
+
+ private string delimiter;
+ private char delimiterFirstChar;
+ private char[] buffer;
+ private int bufferSize;
+ private int charsRead;
+ private int bufferPosition;
+ private int rowStartPosition;
+ private int fieldStartPosition;
+ private int row;
+ private int rawRow;
+ private long charCount;
+ private long byteCount;
+ private bool inQuotes;
+ private bool inEscape;
+ private Field[] fields;
+ private string[] processedFields;
+ private int fieldsPosition;
+ private bool disposed;
+ private int quoteCount;
+ private char[] processFieldBuffer;
+ private int processFieldBufferSize;
+ private ParserState state;
+ private int delimiterPosition = 1;
+ private int newLinePosition = 1;
+ private bool fieldIsBadData;
+ private bool fieldIsQuoted;
+ private bool isProcessingField;
+ private bool isRecordProcessed;
+ private string[]? record;
+
+ /// <inheritdoc/>
+ public long CharCount => charCount;
+
+ /// <inheritdoc/>
+ public long ByteCount => byteCount;
+
+ /// <inheritdoc/>
+ public int Row => row;
+
+ /// <inheritdoc/>
+ public string[]? Record
+ {
+ get
+ {
+ if (isRecordProcessed == true)
+ {
+ return this.record;
+ }
+
+ if (fieldsPosition == 0)
+ {
+ return null;
+ }
+
+ var record = new string[fieldsPosition];
+
+ for (var i = 0; i < record.Length; i++)
+ {
+ record[i] = this[i];
+ }
+
+ this.record = record;
+ isRecordProcessed = true;
+
+ return this.record;
+ }
+ }
+
+ /// <inheritdoc/>
+ public string RawRecord => new string(buffer, rowStartPosition, bufferPosition - rowStartPosition);
+
+ /// <inheritdoc/>
+ public int Count => fieldsPosition;
+
+ /// <inheritdoc/>
+ public int RawRow => rawRow;
+
+ /// <inheritdoc/>
+ public string Delimiter => delimiter;
+
+ /// <inheritdoc/>
+ public CsvContext Context { get; private set; }
+
+ /// <inheritdoc/>
+ public IParserConfiguration Configuration => configuration;
+
+ /// <inheritdoc/>
+ public string this[int index]
+ {
+ get
+ {
+ if (isProcessingField)
+ {
+ var message =
+ $"You can't access {nameof(IParser)}[int] or {nameof(IParser)}.{nameof(IParser.Record)} inside of the {nameof(BadDataFound)} callback. " +
+ $"Use {nameof(BadDataFoundArgs)}.{nameof(BadDataFoundArgs.Field)} and {nameof(BadDataFoundArgs)}.{nameof(BadDataFoundArgs.RawRecord)} instead."
+ ;
+
+ throw new ParserException(Context, message);
+ }
+
+ isProcessingField = true;
+
+ var field = GetField(index);
+
+ isProcessingField = false;
+
+ return field;
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvParser"/> class.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="culture">The culture.</param>
+ /// <param name="leaveOpen">if set to <c>true</c> [leave open].</param>
+ public CsvParser(TextReader reader, CultureInfo culture, bool leaveOpen = false) : this(reader, new CsvConfiguration(culture), leaveOpen) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvParser"/> class.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="configuration">The configuration.</param>
+ /// <param name="leaveOpen">if set to <c>true</c> [leave open].</param>
+ public CsvParser(TextReader reader, IParserConfiguration configuration, bool leaveOpen = false)
+ {
+ this.reader = reader ?? throw new ArgumentNullException(nameof(reader));
+ this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
+
+ configuration.Validate();
+
+ Context = new CsvContext(this);
+
+ allowComments = configuration.AllowComments;
+ badDataFound = configuration.BadDataFound;
+ bufferSize = configuration.BufferSize;
+ cacheFields = configuration.CacheFields;
+ comment = configuration.Comment;
+ countBytes = configuration.CountBytes;
+ delimiter = configuration.Delimiter;
+ delimiterFirstChar = configuration.Delimiter[0];
+ delimiterValues = configuration.DetectDelimiterValues;
+ detectDelimiter = configuration.DetectDelimiter;
+ encoding = configuration.Encoding;
+ escape = configuration.Escape;
+ ignoreBlankLines = configuration.IgnoreBlankLines;
+ isNewLineSet = configuration.IsNewLineSet;
+ this.leaveOpen = leaveOpen;
+ lineBreakInQuotedFieldIsBadData = configuration.LineBreakInQuotedFieldIsBadData;
+ maxFieldSize = configuration.MaxFieldSize;
+ newLine = configuration.NewLine;
+ newLineFirstChar = configuration.NewLine[0];
+ mode = configuration.Mode;
+ processFieldBufferSize = configuration.ProcessFieldBufferSize;
+ quote = configuration.Quote;
+ whiteSpaceChars = configuration.WhiteSpaceChars;
+ trimOptions = configuration.TrimOptions;
+
+ buffer = new char[bufferSize];
+ processFieldBuffer = new char[processFieldBufferSize];
+ fields = new Field[128];
+ processedFields = new string[128];
+ }
+
+ /// <inheritdoc/>
+ public bool Read()
+ {
+ isRecordProcessed = false;
+ rowStartPosition = bufferPosition;
+ fieldStartPosition = rowStartPosition;
+ fieldsPosition = 0;
+ quoteCount = 0;
+ row++;
+ rawRow++;
+ var c = '\0';
+ var cPrev = c;
+
+ while (true)
+ {
+ if (bufferPosition >= charsRead)
+ {
+ if (!FillBuffer())
+ {
+ return ReadEndOfFile();
+ }
+
+ if (row == 1 && detectDelimiter)
+ {
+ DetectDelimiter();
+ }
+ }
+
+ if (ReadLine(ref c, ref cPrev) == ReadLineResult.Complete)
+ {
+ return true;
+ }
+ }
+ }
+
+ /// <inheritdoc/>
+ public async Task<bool> ReadAsync()
+ {
+ isRecordProcessed = false;
+ rowStartPosition = bufferPosition;
+ fieldStartPosition = rowStartPosition;
+ fieldsPosition = 0;
+ quoteCount = 0;
+ row++;
+ rawRow++;
+ var c = '\0';
+ var cPrev = c;
+
+ while (true)
+ {
+ if (bufferPosition >= charsRead)
+ {
+ if (!await FillBufferAsync().ConfigureAwait(false))
+ {
+ return ReadEndOfFile();
+ }
+
+ if (row == 1 && detectDelimiter)
+ {
+ DetectDelimiter();
+ }
+ }
+
+ if (ReadLine(ref c, ref cPrev) == ReadLineResult.Complete)
+ {
+ return true;
+ }
+ }
+ }
+
+ private void DetectDelimiter()
+ {
+ var text = new string(buffer, 0, charsRead);
+ var newDelimiter = configuration.GetDelimiter(new GetDelimiterArgs(text, configuration));
+ if (newDelimiter != null)
+ {
+ delimiter = newDelimiter;
+ delimiterFirstChar = newDelimiter[0];
+ configuration.Validate();
+ }
+ }
+
+ private ReadLineResult ReadLine(ref char c, ref char cPrev)
+ {
+ while (bufferPosition < charsRead)
+ {
+ if (state != ParserState.None)
+ {
+ // Continue the state before doing anything else.
+ ReadLineResult result;
+ switch (state)
+ {
+ case ParserState.Spaces:
+ result = ReadSpaces(ref c);
+ break;
+ case ParserState.BlankLine:
+ result = ReadBlankLine(ref c);
+ break;
+ case ParserState.Delimiter:
+ result = ReadDelimiter(ref c);
+ break;
+ case ParserState.LineEnding:
+ result = ReadLineEnding(ref c);
+ break;
+ case ParserState.NewLine:
+ result = ReadNewLine(ref c);
+ break;
+ default:
+ throw new InvalidOperationException($"Parser state '{state}' is not valid.");
+ }
+
+ var shouldReturn =
+ // Buffer needs to be filled.
+ result == ReadLineResult.Incomplete ||
+ // Done reading row.
+ result == ReadLineResult.Complete && (state == ParserState.LineEnding || state == ParserState.NewLine)
+ ;
+
+ if (result == ReadLineResult.Complete)
+ {
+ state = ParserState.None;
+ }
+
+ if (shouldReturn)
+ {
+ return result;
+ }
+ }
+
+ cPrev = c;
+ c = buffer[bufferPosition];
+ bufferPosition++;
+ charCount++;
+
+ if (countBytes)
+ {
+ byteCount += encoding.GetByteCount(new char[] { c });
+ }
+
+ if (maxFieldSize > 0 && bufferPosition - fieldStartPosition - 1 > maxFieldSize)
+ {
+ throw new MaxFieldSizeException(Context);
+ }
+
+ var isFirstCharOfRow = rowStartPosition == bufferPosition - 1;
+ if (isFirstCharOfRow && (allowComments && c == comment || ignoreBlankLines && ((c == '\r' || c == '\n') && !isNewLineSet || c == newLineFirstChar && isNewLineSet)))
+ {
+ state = ParserState.BlankLine;
+ var result = ReadBlankLine(ref c);
+ if (result == ReadLineResult.Complete)
+ {
+ state = ParserState.None;
+
+ continue;
+ }
+ else
+ {
+ return ReadLineResult.Incomplete;
+ }
+ }
+
+ if (mode == CsvMode.RFC4180)
+ {
+ var isFirstCharOfField = fieldStartPosition == bufferPosition - 1;
+ if (isFirstCharOfField)
+ {
+ if ((trimOptions & TrimOptions.Trim) == TrimOptions.Trim && ArrayHelper.Contains(whiteSpaceChars, c))
+ {
+ // Skip through whitespace. This is so we can process the field later.
+ var result = ReadSpaces(ref c);
+ if (result == ReadLineResult.Incomplete)
+ {
+ fieldStartPosition = bufferPosition;
+ return result;
+ }
+ }
+
+ // Fields are only quoted if the first character is a quote.
+ // If not, read until a delimiter or newline is found.
+ fieldIsQuoted = c == quote;
+ }
+
+ if (fieldIsQuoted)
+ {
+ if (c == quote || c == escape)
+ {
+ quoteCount++;
+
+ if (!inQuotes && !isFirstCharOfField && cPrev != escape)
+ {
+ fieldIsBadData = true;
+ }
+ else if (!fieldIsBadData)
+ {
+ // Don't process field quotes after bad data has been detected.
+ inQuotes = !inQuotes;
+ }
+ }
+
+ if (inQuotes)
+ {
+ if (c == '\r' || c == '\n' && cPrev != '\r')
+ {
+ rawRow++;
+ }
+
+ // We don't care about anything else if we're in quotes.
+ continue;
+ }
+ }
+ else
+ {
+ if (c == quote || c == escape)
+ {
+ // If the field isn't quoted but contains a
+ // quote or escape, it's has bad data.
+ fieldIsBadData = true;
+ }
+ }
+ }
+ else if (mode == CsvMode.Escape)
+ {
+ if (inEscape)
+ {
+ inEscape = false;
+
+ continue;
+ }
+
+ if (c == escape)
+ {
+ inEscape = true;
+
+ continue;
+ }
+ }
+
+ if (c == delimiterFirstChar)
+ {
+ state = ParserState.Delimiter;
+ var result = ReadDelimiter(ref c);
+ if (result == ReadLineResult.Incomplete)
+ {
+ return result;
+ }
+
+ state = ParserState.None;
+
+ continue;
+ }
+
+ if (!isNewLineSet && (c == '\r' || c == '\n'))
+ {
+ state = ParserState.LineEnding;
+ var result = ReadLineEnding(ref c);
+ if (result == ReadLineResult.Complete)
+ {
+ state = ParserState.None;
+ }
+
+ return result;
+ }
+
+ if (isNewLineSet && c == newLineFirstChar)
+ {
+ state = ParserState.NewLine;
+ var result = ReadNewLine(ref c);
+ if (result == ReadLineResult.Complete)
+ {
+ state = ParserState.None;
+ }
+
+ return result;
+ }
+ }
+
+ return ReadLineResult.Incomplete;
+ }
+
+ private ReadLineResult ReadSpaces(ref char c)
+ {
+ while (ArrayHelper.Contains(whiteSpaceChars, c))
+ {
+ if (bufferPosition >= charsRead)
+ {
+ return ReadLineResult.Incomplete;
+ }
+
+ c = buffer[bufferPosition];
+ bufferPosition++;
+ charCount++;
+ if (countBytes)
+ {
+ byteCount += encoding.GetByteCount(new char[] { c });
+ }
+ }
+
+ return ReadLineResult.Complete;
+ }
+
+ private ReadLineResult ReadBlankLine(ref char c)
+ {
+ while (bufferPosition < charsRead)
+ {
+ if (c == '\r' || c == '\n')
+ {
+ var result = ReadLineEnding(ref c);
+ if (result == ReadLineResult.Complete)
+ {
+ rowStartPosition = bufferPosition;
+ fieldStartPosition = rowStartPosition;
+ row++;
+ rawRow++;
+ }
+
+ return result;
+ }
+
+ c = buffer[bufferPosition];
+ bufferPosition++;
+ charCount++;
+ if (countBytes)
+ {
+ byteCount += encoding.GetByteCount(new char[] { c });
+ }
+ }
+
+ return ReadLineResult.Incomplete;
+ }
+
+ private ReadLineResult ReadDelimiter(ref char c)
+ {
+ for (var i = delimiterPosition; i < delimiter.Length; i++)
+ {
+ if (bufferPosition >= charsRead)
+ {
+ return ReadLineResult.Incomplete;
+ }
+
+ delimiterPosition++;
+
+ c = buffer[bufferPosition];
+ if (c != delimiter[i])
+ {
+ c = buffer[bufferPosition - 1];
+ delimiterPosition = 1;
+
+ return ReadLineResult.Complete;
+ }
+
+ bufferPosition++;
+ charCount++;
+ if (countBytes)
+ {
+ byteCount += encoding.GetByteCount(new[] { c });
+ }
+
+ if (bufferPosition >= charsRead)
+ {
+ return ReadLineResult.Incomplete;
+ }
+ }
+
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition - delimiter.Length);
+
+ fieldStartPosition = bufferPosition;
+ delimiterPosition = 1;
+ fieldIsBadData = false;
+
+ return ReadLineResult.Complete;
+ }
+
+ private ReadLineResult ReadLineEnding(ref char c)
+ {
+ var lessChars = 1;
+
+ if (c == '\r')
+ {
+ if (bufferPosition >= charsRead)
+ {
+ return ReadLineResult.Incomplete;
+ }
+
+ c = buffer[bufferPosition];
+
+ if (c == '\n')
+ {
+ lessChars++;
+ bufferPosition++;
+ charCount++;
+ if (countBytes)
+ {
+ byteCount += encoding.GetByteCount(new char[] { c });
+ }
+ }
+ }
+
+ if (state == ParserState.LineEnding)
+ {
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition - lessChars);
+ }
+
+ fieldIsBadData = false;
+
+ return ReadLineResult.Complete;
+ }
+
+ private ReadLineResult ReadNewLine(ref char c)
+ {
+ for (var i = newLinePosition; i < newLine.Length; i++)
+ {
+ if (bufferPosition >= charsRead)
+ {
+ return ReadLineResult.Incomplete;
+ }
+
+ newLinePosition++;
+
+ c = buffer[bufferPosition];
+ if (c != newLine[i])
+ {
+ c = buffer[bufferPosition - 1];
+ newLinePosition = 1;
+
+ return ReadLineResult.Complete;
+ }
+
+ bufferPosition++;
+ charCount++;
+ if (countBytes)
+ {
+ byteCount += encoding.GetByteCount(new[] { c });
+ }
+
+ if (bufferPosition >= charsRead)
+ {
+ return ReadLineResult.Incomplete;
+ }
+ }
+
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition - newLine.Length);
+
+ fieldStartPosition = bufferPosition;
+ newLinePosition = 1;
+ fieldIsBadData = false;
+
+ return ReadLineResult.Complete;
+ }
+
+ private bool ReadEndOfFile()
+ {
+ var state = this.state;
+ this.state = ParserState.None;
+
+ if (state == ParserState.BlankLine)
+ {
+ return false;
+ }
+
+ if (state == ParserState.Delimiter)
+ {
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition - delimiter.Length);
+
+ fieldStartPosition = bufferPosition;
+
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition);
+
+ return true;
+ }
+
+ if (state == ParserState.LineEnding)
+ {
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition - 1);
+
+ return true;
+ }
+
+ if (state == ParserState.NewLine)
+ {
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition - newLine.Length);
+
+ return true;
+ }
+
+ if (rowStartPosition < bufferPosition)
+ {
+ AddField(fieldStartPosition, bufferPosition - fieldStartPosition);
+ }
+
+ return fieldsPosition > 0;
+ }
+
+ private void AddField(int start, int length)
+ {
+ if (fieldsPosition >= fields.Length)
+ {
+ var newSize = fields.Length * 2;
+ Array.Resize(ref fields, newSize);
+ Array.Resize(ref processedFields, newSize);
+ }
+
+ ref var field = ref fields[fieldsPosition];
+ field.Start = start - rowStartPosition;
+ field.Length = length;
+ field.QuoteCount = quoteCount;
+ field.IsBad = fieldIsBadData;
+ field.IsProcessed = false;
+
+ fieldsPosition++;
+ quoteCount = 0;
+ }
+
+ private bool FillBuffer()
+ {
+ // Don't forget the async method below.
+
+ if (rowStartPosition == 0 && charCount > 0 && charsRead == bufferSize)
+ {
+ // The record is longer than the memory buffer. Increase the buffer.
+ bufferSize *= 2;
+ var tempBuffer = new char[bufferSize];
+ buffer.CopyTo(tempBuffer, 0);
+ buffer = tempBuffer;
+ }
+
+ var charsLeft = Math.Max(charsRead - rowStartPosition, 0);
+
+ Array.Copy(buffer, rowStartPosition, buffer, 0, charsLeft);
+
+ fieldStartPosition -= rowStartPosition;
+ rowStartPosition = 0;
+ bufferPosition = charsLeft;
+
+ charsRead = reader.Read(buffer, charsLeft, buffer.Length - charsLeft);
+ if (charsRead == 0)
+ {
+ return false;
+ }
+
+ charsRead += charsLeft;
+
+ return true;
+ }
+
+ private async Task<bool> FillBufferAsync()
+ {
+ if (rowStartPosition == 0 && charCount > 0 && charsRead == bufferSize)
+ {
+ // The record is longer than the memory buffer. Increase the buffer.
+ bufferSize *= 2;
+ var tempBuffer = new char[bufferSize];
+ buffer.CopyTo(tempBuffer, 0);
+ buffer = tempBuffer;
+ }
+
+ var charsLeft = Math.Max(charsRead - rowStartPosition, 0);
+
+ Array.Copy(buffer, rowStartPosition, buffer, 0, charsLeft);
+
+ fieldStartPosition -= rowStartPosition;
+ rowStartPosition = 0;
+ bufferPosition = charsLeft;
+
+ charsRead = await reader.ReadAsync(buffer, charsLeft, buffer.Length - charsLeft).ConfigureAwait(false);
+ if (charsRead == 0)
+ {
+ return false;
+ }
+
+ charsRead += charsLeft;
+
+ return true;
+ }
+
+ private string GetField(int index)
+ {
+ if (index > fieldsPosition)
+ {
+ throw new IndexOutOfRangeException();
+ }
+
+ ref var field = ref fields[index];
+
+ if (field.Length == 0)
+ {
+ return string.Empty;
+ }
+
+ if (field.IsProcessed)
+ {
+ return processedFields[index];
+ }
+
+ var start = field.Start + rowStartPosition;
+ var length = field.Length;
+ var quoteCount = field.QuoteCount;
+
+ ProcessedField processedField;
+ switch (mode)
+ {
+ case CsvMode.RFC4180:
+ processedField = field.IsBad
+ ? ProcessRFC4180BadField(start, length)
+ : ProcessRFC4180Field(start, length, quoteCount);
+ break;
+ case CsvMode.Escape:
+ processedField = ProcessEscapeField(start, length);
+ break;
+ case CsvMode.NoEscape:
+ processedField = ProcessNoEscapeField(start, length);
+ break;
+ default:
+ throw new InvalidOperationException($"ParseMode '{mode}' is not handled.");
+ }
+
+ var value = cacheFields
+ ? fieldCache.GetField(processedField.Buffer, processedField.Start, processedField.Length)
+ : new string(processedField.Buffer, processedField.Start, processedField.Length);
+
+ processedFields[index] = value;
+ field.IsProcessed = true;
+
+ return value;
+ }
+
+ /// <summary>
+ /// Processes a field that complies with RFC4180.
+ /// </summary>
+ /// <param name="start">The start index of the field.</param>
+ /// <param name="length">The length of the field.</param>
+ /// <param name="quoteCount">The number of counted quotes.</param>
+ /// <returns>The processed field.</returns>
+ protected ProcessedField ProcessRFC4180Field(int start, int length, int quoteCount)
+ {
+ var newStart = start;
+ var newLength = length;
+
+ if ((trimOptions & TrimOptions.Trim) == TrimOptions.Trim)
+ {
+ ArrayHelper.Trim(buffer, ref newStart, ref newLength, whiteSpaceChars);
+ }
+
+ if (quoteCount == 0)
+ {
+ // Not quoted.
+ // No processing needed.
+
+ return new ProcessedField(newStart, newLength, buffer);
+ }
+
+ if (buffer[newStart] != quote || buffer[newStart + newLength - 1] != quote || newLength == 1 && buffer[newStart] == quote)
+ {
+ // If the field doesn't have quotes on the ends, or the field is a single quote char, it's bad data.
+ return ProcessRFC4180BadField(start, length);
+ }
+
+ if (lineBreakInQuotedFieldIsBadData)
+ {
+ for (var i = newStart; i < newStart + newLength; i++)
+ {
+ if (buffer[i] == '\r' || buffer[i] == '\n')
+ {
+ return ProcessRFC4180BadField(start, length);
+ }
+ }
+ }
+
+ // Remove the quotes from the ends.
+ newStart += 1;
+ newLength -= 2;
+
+ if ((trimOptions & TrimOptions.InsideQuotes) == TrimOptions.InsideQuotes)
+ {
+ ArrayHelper.Trim(buffer, ref newStart, ref newLength, whiteSpaceChars);
+ }
+
+ if (quoteCount == 2)
+ {
+ // The only quotes are the ends of the field.
+ // No more processing is needed.
+ return new ProcessedField(newStart, newLength, buffer);
+ }
+
+ if (newLength > processFieldBuffer.Length)
+ {
+ // Make sure the field processing buffer is large engough.
+ while (newLength > processFieldBufferSize)
+ {
+ processFieldBufferSize *= 2;
+ }
+
+ processFieldBuffer = new char[processFieldBufferSize];
+ }
+
+ // Remove escapes.
+ var inEscape = false;
+ var position = 0;
+ for (var i = newStart; i < newStart + newLength; i++)
+ {
+ var c = buffer[i];
+
+ if (inEscape)
+ {
+ inEscape = false;
+ }
+ else if (c == escape)
+ {
+ inEscape = true;
+
+ continue;
+ }
+
+ processFieldBuffer[position] = c;
+ position++;
+ }
+
+ return new ProcessedField(0, position, processFieldBuffer);
+ }
+
+ /// <summary>
+ /// Processes a field that does not comply with RFC4180.
+ /// </summary>
+ /// <param name="start">The start index of the field.</param>
+ /// <param name="length">The length of the field.</param>
+ /// <returns>The processed field.</returns>
+ protected ProcessedField ProcessRFC4180BadField(int start, int length)
+ {
+ // If field is already known to be bad, different rules can be applied.
+
+ var args = new BadDataFoundArgs(new string(buffer, start, length), RawRecord, Context);
+ badDataFound?.Invoke(args);
+
+ var newStart = start;
+ var newLength = length;
+
+ if ((trimOptions & TrimOptions.Trim) == TrimOptions.Trim)
+ {
+ ArrayHelper.Trim(buffer, ref newStart, ref newLength, whiteSpaceChars);
+ }
+
+ if (buffer[newStart] != quote)
+ {
+ // If the field doesn't start with a quote, don't process it.
+ return new ProcessedField(newStart, newLength, buffer);
+ }
+
+ if (newLength > processFieldBuffer.Length)
+ {
+ // Make sure the field processing buffer is large engough.
+ while (newLength > processFieldBufferSize)
+ {
+ processFieldBufferSize *= 2;
+ }
+
+ processFieldBuffer = new char[processFieldBufferSize];
+ }
+
+ // Remove escapes until the last quote is found.
+ var inEscape = false;
+ var position = 0;
+ var c = '\0';
+ var doneProcessing = false;
+ for (var i = newStart + 1; i < newStart + newLength; i++)
+ {
+ var cPrev = c;
+ c = buffer[i];
+
+ // a,"b",c
+ // a,"b "" c",d
+ // a,"b "c d",e
+
+ if (inEscape)
+ {
+ inEscape = false;
+
+ if (c == quote)
+ {
+ // Ignore the quote after an escape.
+ continue;
+ }
+ else if (cPrev == quote)
+ {
+ // The escape and quote are the same character.
+ // This is the end of the field.
+ // Don't process escapes for the rest of the field.
+ doneProcessing = true;
+ }
+ }
+
+ if (c == escape && !doneProcessing)
+ {
+ inEscape = true;
+
+ continue;
+ }
+
+ processFieldBuffer[position] = c;
+ position++;
+ }
+
+ return new ProcessedField(0, position, processFieldBuffer);
+ }
+
+ /// <summary>
+ /// Processes an escaped field.
+ /// </summary>
+ /// <param name="start">The start index of the field.</param>
+ /// <param name="length">The length of the field.</param>
+ /// <returns>The processed field.</returns>
+ protected ProcessedField ProcessEscapeField(int start, int length)
+ {
+ var newStart = start;
+ var newLength = length;
+
+ if ((trimOptions & TrimOptions.Trim) == TrimOptions.Trim)
+ {
+ ArrayHelper.Trim(buffer, ref newStart, ref newLength, whiteSpaceChars);
+ }
+
+ if (newLength > processFieldBuffer.Length)
+ {
+ // Make sure the field processing buffer is large engough.
+ while (newLength > processFieldBufferSize)
+ {
+ processFieldBufferSize *= 2;
+ }
+
+ processFieldBuffer = new char[processFieldBufferSize];
+ }
+
+ // Remove escapes.
+ var inEscape = false;
+ var position = 0;
+ for (var i = newStart; i < newStart + newLength; i++)
+ {
+ var c = buffer[i];
+
+ if (inEscape)
+ {
+ inEscape = false;
+ }
+ else if (c == escape)
+ {
+ inEscape = true;
+ continue;
+ }
+
+ processFieldBuffer[position] = c;
+ position++;
+ }
+
+ return new ProcessedField(0, position, processFieldBuffer);
+ }
+
+ /// <inheritdoc/>
+ /// <summary>
+ /// Processes an non-escaped field.
+ /// </summary>
+ /// <param name="start">The start index of the field.</param>
+ /// <param name="length">The length of the field.</param>
+ /// <returns>The processed field.</returns>
+ protected ProcessedField ProcessNoEscapeField(int start, int length)
+ {
+ var newStart = start;
+ var newLength = length;
+
+ if ((trimOptions & TrimOptions.Trim) == TrimOptions.Trim)
+ {
+ ArrayHelper.Trim(buffer, ref newStart, ref newLength, whiteSpaceChars);
+ }
+
+ return new ProcessedField(newStart, newLength, buffer);
+ }
+
+ /// <inheritdoc/>
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Disposes the object.
+ /// </summary>
+ /// <param name="disposing">Indicates if the object is being disposed.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ // Dispose managed state (managed objects)
+
+ if (!leaveOpen)
+ {
+ reader?.Dispose();
+ }
+ }
+
+ // Free unmanaged resources (unmanaged objects) and override finalizer
+ // Set large fields to null
+
+ disposed = true;
+ }
+
+ /// <summary>
+ /// Processes a raw field based on configuration.
+ /// This will remove quotes, remove escapes, and trim if configured to.
+ /// </summary>
+ [DebuggerDisplay("Start = {Start}, Length = {Length}, Buffer.Length = {Buffer.Length}")]
+ protected readonly struct ProcessedField
+ {
+ /// <summary>
+ /// The start of the field in the buffer.
+ /// </summary>
+ public readonly int Start;
+
+ /// <summary>
+ /// The length of the field in the buffer.
+ /// </summary>
+ public readonly int Length;
+
+ /// <summary>
+ /// The buffer that contains the field.
+ /// </summary>
+ public readonly char[] Buffer;
+
+ /// <summary>
+ /// Creates a new instance of ProcessedField.
+ /// </summary>
+ /// <param name="start">The start of the field in the buffer.</param>
+ /// <param name="length">The length of the field in the buffer.</param>
+ /// <param name="buffer">The buffer that contains the field.</param>
+ public ProcessedField(int start, int length, char[] buffer)
+ {
+ Start = start;
+ Length = length;
+ Buffer = buffer;
+ }
+ }
+
+ private enum ReadLineResult
+ {
+ None = 0,
+ Complete,
+ Incomplete,
+ }
+
+ private enum ParserState
+ {
+ None = 0,
+ Spaces,
+ BlankLine,
+ Delimiter,
+ LineEnding,
+ NewLine,
+ }
+
+ [DebuggerDisplay("Start = {Start}, Length = {Length}, QuoteCount = {QuoteCount}, IsBad = {IsBad}")]
+ private struct Field
+ {
+ /// <summary>
+ /// Starting position of the field.
+ /// This is an offset from <see cref="rowStartPosition"/>.
+ /// </summary>
+ public int Start;
+
+ public int Length;
+
+ public int QuoteCount;
+
+ public bool IsBad;
+
+ public bool IsProcessed;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvReader.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvReader.cs
new file mode 100644
index 0000000..2b8ee84
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvReader.cs
@@ -0,0 +1,1419 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.IO;
+using CsvHelper.Configuration;
+using CsvHelper.TypeConversion;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+using CsvHelper.Expressions;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Configuration;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Reads data that was parsed from <see cref="IParser" />.
+ /// </summary>
+ public class CsvReader : IReader
+ {
+ private readonly Lazy<RecordManager> recordManager;
+ private readonly bool detectColumnCountChanges;
+ private readonly Dictionary<string, List<int>> namedIndexes = new Dictionary<string, List<int>>();
+ private readonly Dictionary<string, (string, int)> namedIndexCache = new Dictionary<string, (string, int)>();
+ private readonly Dictionary<Type, TypeConverterOptions> typeConverterOptionsCache = new Dictionary<Type, TypeConverterOptions>();
+ private readonly MemberMapData reusableMemberMapData = new MemberMapData(null);
+ private readonly bool hasHeaderRecord;
+ private readonly HeaderValidated headerValidated;
+ private readonly ShouldSkipRecord? shouldSkipRecord;
+ private readonly ReadingExceptionOccurred readingExceptionOccurred;
+ private readonly CultureInfo cultureInfo;
+ private readonly bool ignoreBlankLines;
+ private readonly MissingFieldFound missingFieldFound;
+ private readonly bool includePrivateMembers;
+ private readonly PrepareHeaderForMatch prepareHeaderForMatch;
+
+ private CsvContext context;
+ private bool disposed;
+ private IParser parser;
+ private int columnCount;
+ private int currentIndex = -1;
+ private bool hasBeenRead;
+ private string[]? headerRecord;
+
+ /// <inheritdoc/>
+ public virtual int ColumnCount => columnCount;
+
+ /// <inheritdoc/>
+ public virtual int CurrentIndex => currentIndex;
+
+ /// <inheritdoc/>
+ public virtual string[]? HeaderRecord => headerRecord;
+
+ /// <inheritdoc/>
+ public virtual CsvContext Context => context;
+
+ /// <inheritdoc/>
+ public virtual IReaderConfiguration Configuration { get; private set; }
+
+ /// <inheritdoc/>
+ public virtual IParser Parser => parser;
+
+ /// <summary>
+ /// Creates a new CSV reader using the given <see cref="TextReader" />.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="culture">The culture.</param>
+ /// <param name="leaveOpen"><c>true</c> to leave the <see cref="TextReader"/> open after the <see cref="CsvReader"/> object is disposed, otherwise <c>false</c>.</param>
+ public CsvReader(TextReader reader, CultureInfo culture, bool leaveOpen = false) : this(new CsvParser(reader, culture, leaveOpen)) { }
+
+ /// <summary>
+ /// Creates a new CSV reader using the given <see cref="TextReader" /> and
+ /// <see cref="CsvHelper.Configuration.CsvConfiguration" /> and <see cref="CsvParser" /> as the default parser.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="configuration">The configuration.</param>
+ /// <param name="leaveOpen"><c>true</c> to leave the <see cref="TextReader"/> open after the <see cref="CsvReader"/> object is disposed, otherwise <c>false</c>.</param>
+ public CsvReader(TextReader reader, IReaderConfiguration configuration, bool leaveOpen = false) : this(new CsvParser(reader, configuration, leaveOpen)) { }
+
+ /// <summary>
+ /// Creates a new CSV reader using the given <see cref="IParser" />.
+ /// </summary>
+ /// <param name="parser">The <see cref="IParser" /> used to parse the CSV file.</param>
+ public CsvReader(IParser parser)
+ {
+ Configuration = parser.Configuration as IReaderConfiguration ?? throw new ConfigurationException($"The {nameof(IParser)} configuration must implement {nameof(IReaderConfiguration)} to be used in {nameof(CsvReader)}.");
+
+ this.parser = parser ?? throw new ArgumentNullException(nameof(parser));
+ context = parser.Context ?? throw new InvalidOperationException($"For {nameof(IParser)} to be used in {nameof(CsvReader)}, {nameof(IParser.Context)} must also implement {nameof(CsvContext)}.");
+ context.Reader = this;
+ recordManager = new Lazy<RecordManager>(() => ObjectResolver.Current.Resolve<RecordManager>(this));
+
+ cultureInfo = Configuration.CultureInfo;
+ detectColumnCountChanges = Configuration.DetectColumnCountChanges;
+ hasHeaderRecord = Configuration.HasHeaderRecord;
+ headerValidated = Configuration.HeaderValidated;
+ ignoreBlankLines = Configuration.IgnoreBlankLines;
+ includePrivateMembers = Configuration.IncludePrivateMembers;
+ missingFieldFound = Configuration.MissingFieldFound;
+ prepareHeaderForMatch = Configuration.PrepareHeaderForMatch;
+ readingExceptionOccurred = Configuration.ReadingExceptionOccurred;
+ shouldSkipRecord = Configuration.ShouldSkipRecord;
+ }
+
+ /// <inheritdoc/>
+ public virtual bool ReadHeader()
+ {
+ if (!hasHeaderRecord)
+ {
+ throw new ReaderException(context, "Configuration.HasHeaderRecord is false.");
+ }
+
+ headerRecord = parser.Record;
+ ParseNamedIndexes();
+
+ return headerRecord != null;
+ }
+
+ /// <summary>
+ /// Validates the header to be of the given type.
+ /// </summary>
+ /// <typeparam name="T">The expected type of the header</typeparam>
+ public virtual void ValidateHeader<T>()
+ {
+ ValidateHeader(typeof(T));
+ }
+
+ /// <summary>
+ /// Validates the header to be of the given type.
+ /// </summary>
+ /// <param name="type">The expected type of the header.</param>
+ public virtual void ValidateHeader(Type type)
+ {
+ if (hasHeaderRecord == false)
+ {
+ throw new InvalidOperationException($"Validation can't be performed on a the header if no header exists. {nameof(Configuration.HasHeaderRecord)} can't be false.");
+ }
+
+ CheckHasBeenRead();
+
+ if (headerRecord == null)
+ {
+ throw new InvalidOperationException($"The header must be read before it can be validated.");
+ }
+
+ if (context.Maps[type] == null)
+ {
+ context.Maps.Add(context.AutoMap(type));
+ }
+
+ var map = context.Maps[type];
+ var invalidHeaders = new List<InvalidHeader>();
+ ValidateHeader(map, invalidHeaders);
+
+ var args = new HeaderValidatedArgs(invalidHeaders.ToArray(), context);
+ headerValidated?.Invoke(args);
+ }
+
+ /// <summary>
+ /// Validates the header to be of the given type.
+ /// </summary>
+ /// <param name="map">The mapped classes.</param>
+ /// <param name="invalidHeaders">The invalid headers.</param>
+ protected virtual void ValidateHeader(ClassMap map, List<InvalidHeader> invalidHeaders)
+ {
+ foreach (var parameter in map.ParameterMaps)
+ {
+ if (parameter.Data.Ignore)
+ {
+ continue;
+ }
+
+ if (parameter.Data.IsConstantSet)
+ {
+ // If ConvertUsing and Constant don't require a header.
+ continue;
+ }
+
+ if (parameter.Data.IsIndexSet && !parameter.Data.IsNameSet)
+ {
+ // If there is only an index set, we don't want to validate the header name.
+ continue;
+ }
+
+ if (parameter.ConstructorTypeMap != null)
+ {
+ ValidateHeader(parameter.ConstructorTypeMap, invalidHeaders);
+ }
+ else if (parameter.ReferenceMap != null)
+ {
+ ValidateHeader(parameter.ReferenceMap.Data.Mapping, invalidHeaders);
+ }
+ else
+ {
+ var index = GetFieldIndex(parameter.Data.Names, parameter.Data.NameIndex, true);
+ var isValid = index != -1 || parameter.Data.IsOptional;
+ if (!isValid)
+ {
+ invalidHeaders.Add(new InvalidHeader { Index = parameter.Data.NameIndex, Names = parameter.Data.Names.ToList() });
+ }
+ }
+ }
+
+ foreach (var memberMap in map.MemberMaps)
+ {
+ if (memberMap.Data.Ignore || !CanRead(memberMap))
+ {
+ continue;
+ }
+
+ if (memberMap.Data.ReadingConvertExpression != null || memberMap.Data.IsConstantSet)
+ {
+ // If ConvertUsing and Constant don't require a header.
+ continue;
+ }
+
+ if (memberMap.Data.IsIndexSet && !memberMap.Data.IsNameSet)
+ {
+ // If there is only an index set, we don't want to validate the header name.
+ continue;
+ }
+
+ var index = GetFieldIndex(memberMap.Data.Names, memberMap.Data.NameIndex, true);
+ var isValid = index != -1 || memberMap.Data.IsOptional;
+ if (!isValid)
+ {
+ invalidHeaders.Add(new InvalidHeader { Index = memberMap.Data.NameIndex, Names = memberMap.Data.Names.ToList() });
+ }
+ }
+
+ foreach (var referenceMap in map.ReferenceMaps)
+ {
+ if (!CanRead(referenceMap))
+ {
+ continue;
+ }
+
+ ValidateHeader(referenceMap.Data.Mapping, invalidHeaders);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual bool Read()
+ {
+ // Don't forget about the async method below!
+
+ bool hasMoreRecords;
+ do
+ {
+ hasMoreRecords = parser.Read();
+ hasBeenRead = true;
+ }
+ while (hasMoreRecords && (shouldSkipRecord?.Invoke(new ShouldSkipRecordArgs(this)) ?? false));
+
+ currentIndex = -1;
+
+ if (detectColumnCountChanges && hasMoreRecords)
+ {
+ if (columnCount > 0 && columnCount != parser.Count)
+ {
+ var csvException = new BadDataException(string.Empty, parser.RawRecord, context, "An inconsistent number of columns has been detected.");
+
+ var args = new ReadingExceptionOccurredArgs(csvException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ throw csvException;
+ }
+ }
+
+ columnCount = parser.Count;
+ }
+
+ return hasMoreRecords;
+ }
+
+ /// <inheritdoc/>
+ public virtual async Task<bool> ReadAsync()
+ {
+ bool hasMoreRecords;
+ do
+ {
+ hasMoreRecords = await parser.ReadAsync().ConfigureAwait(false);
+ hasBeenRead = true;
+ }
+ while (hasMoreRecords && (shouldSkipRecord?.Invoke(new ShouldSkipRecordArgs(this)) ?? false));
+
+ currentIndex = -1;
+
+ if (detectColumnCountChanges && hasMoreRecords)
+ {
+ if (columnCount > 0 && columnCount != parser.Count)
+ {
+ var csvException = new BadDataException(string.Empty, parser.RawRecord, context, "An inconsistent number of columns has been detected.");
+
+ var args = new ReadingExceptionOccurredArgs(csvException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ throw csvException;
+ }
+ }
+
+ columnCount = parser.Count;
+ }
+
+ return hasMoreRecords;
+ }
+
+ /// <inheritdoc/>
+ public virtual string? this[int index]
+ {
+ get
+ {
+ CheckHasBeenRead();
+
+ return GetField(index);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual string? this[string name]
+ {
+ get
+ {
+ CheckHasBeenRead();
+
+ return GetField(name);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual string? this[string name, int index]
+ {
+ get
+ {
+ CheckHasBeenRead();
+
+ return GetField(name, index);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual string? GetField(int index)
+ {
+ CheckHasBeenRead();
+
+ // Set the current index being used so we
+ // have more information if an error occurs
+ // when reading records.
+ currentIndex = index;
+
+ if (index >= parser.Count || index < 0)
+ {
+ var args = new MissingFieldFoundArgs(null, index, context);
+ missingFieldFound?.Invoke(args);
+ return default;
+ }
+
+ var field = parser[index];
+
+ return field;
+ }
+
+ /// <inheritdoc/>
+ public virtual string? GetField(string name)
+ {
+ CheckHasBeenRead();
+
+ var index = GetFieldIndex(name);
+ if (index < 0)
+ {
+ return null;
+ }
+
+ return GetField(index);
+ }
+
+ /// <inheritdoc/>
+ public virtual string? GetField(string name, int index)
+ {
+ CheckHasBeenRead();
+
+ var fieldIndex = GetFieldIndex(name, index);
+ if (fieldIndex < 0)
+ {
+ return null;
+ }
+
+ return GetField(fieldIndex);
+ }
+
+ /// <inheritdoc/>
+ public virtual object? GetField(Type type, int index)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter(type);
+ return GetField(type, index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual object? GetField(Type type, string name)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter(type);
+ return GetField(type, name, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual object? GetField(Type type, string name, int index)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter(type);
+ return GetField(type, name, index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual object? GetField(Type type, int index, ITypeConverter converter)
+ {
+ CheckHasBeenRead();
+
+ reusableMemberMapData.Index = index;
+ reusableMemberMapData.TypeConverter = converter;
+ if (!typeConverterOptionsCache.TryGetValue(type, out TypeConverterOptions typeConverterOptions))
+ {
+ typeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions { CultureInfo = cultureInfo }, context.TypeConverterOptionsCache.GetOptions(type));
+ typeConverterOptionsCache.Add(type, typeConverterOptions);
+ }
+
+ reusableMemberMapData.TypeConverterOptions = typeConverterOptions;
+
+ var field = GetField(index);
+ return converter.ConvertFromString(field, this, reusableMemberMapData);
+ }
+
+ /// <inheritdoc/>
+ public virtual object? GetField(Type type, string name, ITypeConverter converter)
+ {
+ CheckHasBeenRead();
+
+ var index = GetFieldIndex(name);
+ return GetField(type, index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual object? GetField(Type type, string name, int index, ITypeConverter converter)
+ {
+ CheckHasBeenRead();
+
+ var fieldIndex = GetFieldIndex(name, index);
+ return GetField(type, fieldIndex, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T>(int index)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter<T>();
+ return GetField<T>(index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T>(string name)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter<T>();
+ return GetField<T>(name, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T>(string name, int index)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter<T>();
+ return GetField<T>(name, index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T>(int index, ITypeConverter converter)
+ {
+ CheckHasBeenRead();
+
+ if (index >= parser.Count || index < 0)
+ {
+ currentIndex = index;
+ var args = new MissingFieldFoundArgs(null, index, context);
+ missingFieldFound?.Invoke(args);
+
+ return default;
+ }
+
+ return (T)GetField(typeof(T), index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T>(string name, ITypeConverter converter)
+ {
+ CheckHasBeenRead();
+
+ var index = GetFieldIndex(name);
+ return GetField<T>(index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T>(string name, int index, ITypeConverter converter)
+ {
+ CheckHasBeenRead();
+
+ var fieldIndex = GetFieldIndex(name, index);
+ return GetField<T>(fieldIndex, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T, TConverter>(int index) where TConverter : ITypeConverter
+ {
+ CheckHasBeenRead();
+
+ var converter = ObjectResolver.Current.Resolve<TConverter>();
+ return GetField<T>(index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T, TConverter>(string name) where TConverter : ITypeConverter
+ {
+ CheckHasBeenRead();
+
+ var converter = ObjectResolver.Current.Resolve<TConverter>();
+ return GetField<T>(name, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetField<T, TConverter>(string name, int index) where TConverter : ITypeConverter
+ {
+ CheckHasBeenRead();
+
+ var converter = ObjectResolver.Current.Resolve<TConverter>();
+ return GetField<T>(name, index, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField(Type type, int index, out object? field)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter(type);
+ return TryGetField(type, index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField(Type type, string name, out object? field)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter(type);
+ return TryGetField(type, name, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField(Type type, string name, int index, out object? field)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter(type);
+ return TryGetField(type, name, index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField(Type type, int index, ITypeConverter converter, out object? field)
+ {
+ CheckHasBeenRead();
+
+ // TypeConverter.IsValid() just wraps a
+ // ConvertFrom() call in a try/catch, so lets not
+ // do it twice and just do it ourselves.
+ try
+ {
+ field = GetField(type, index, converter);
+ return true;
+ }
+ catch
+ {
+ field = type.GetTypeInfo().IsValueType ? ObjectResolver.Current.Resolve(type) : null;
+ return false;
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField(Type type, string name, ITypeConverter converter, out object? field)
+ {
+ CheckHasBeenRead();
+
+ var index = GetFieldIndex(name, isTryGet: true);
+ if (index == -1)
+ {
+ field = type.GetTypeInfo().IsValueType ? ObjectResolver.Current.Resolve(type) : null;
+ return false;
+ }
+
+ return TryGetField(type, index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField(Type type, string name, int index, ITypeConverter converter, out object? field)
+ {
+ CheckHasBeenRead();
+
+ var fieldIndex = GetFieldIndex(name, index, true);
+ if (fieldIndex == -1)
+ {
+ field = type.GetTypeInfo().IsValueType ? ObjectResolver.Current.Resolve(type) : null;
+ return false;
+ }
+
+ return TryGetField(type, fieldIndex, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T>(int index, out T? field)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter<T>();
+ return TryGetField(index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T>(string name, out T? field)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter<T>();
+ return TryGetField(name, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T>(string name, int index, out T? field)
+ {
+ CheckHasBeenRead();
+
+ var converter = context.TypeConverterCache.GetConverter<T>();
+ return TryGetField(name, index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T>(int index, ITypeConverter converter, out T? field)
+ {
+ CheckHasBeenRead();
+
+ // TypeConverter.IsValid() just wraps a
+ // ConvertFrom() call in a try/catch, so lets not
+ // do it twice and just do it ourselves.
+ try
+ {
+ field = GetField<T>(index, converter);
+ return true;
+ }
+ catch
+ {
+ field = default;
+ return false;
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T>(string name, ITypeConverter converter, out T? field)
+ {
+ CheckHasBeenRead();
+
+ var index = GetFieldIndex(name, isTryGet: true);
+ if (index == -1)
+ {
+ field = default;
+ return false;
+ }
+
+ return TryGetField(index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T>(string name, int index, ITypeConverter converter, out T? field)
+ {
+ CheckHasBeenRead();
+
+ var fieldIndex = GetFieldIndex(name, index, true);
+ if (fieldIndex == -1)
+ {
+ field = default;
+ return false;
+ }
+
+ return TryGetField(fieldIndex, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T, TConverter>(int index, out T? field) where TConverter : ITypeConverter
+ {
+ CheckHasBeenRead();
+
+ var converter = ObjectResolver.Current.Resolve<TConverter>();
+ return TryGetField(index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T, TConverter>(string name, out T? field) where TConverter : ITypeConverter
+ {
+ CheckHasBeenRead();
+
+ var converter = ObjectResolver.Current.Resolve<TConverter>();
+ return TryGetField(name, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual bool TryGetField<T, TConverter>(string name, int index, out T? field) where TConverter : ITypeConverter
+ {
+ CheckHasBeenRead();
+
+ var converter = ObjectResolver.Current.Resolve<TConverter>();
+ return TryGetField(name, index, converter, out field);
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetRecord<T>()
+ {
+ CheckHasBeenRead();
+
+ if (headerRecord == null && hasHeaderRecord)
+ {
+ ReadHeader();
+ ValidateHeader<T>();
+
+ if (!Read())
+ {
+ return default;
+ }
+ }
+
+ T record;
+ try
+ {
+ record = recordManager.Value.Create<T>();
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ record = default;
+ }
+
+ return record;
+ }
+
+ /// <inheritdoc/>
+ public virtual T? GetRecord<T>(T anonymousTypeDefinition)
+ {
+ if (anonymousTypeDefinition == null)
+ {
+ throw new ArgumentNullException(nameof(anonymousTypeDefinition));
+ }
+
+ if (!anonymousTypeDefinition.GetType().IsAnonymous())
+ {
+ throw new ArgumentException($"Argument is not an anonymous type.", nameof(anonymousTypeDefinition));
+ }
+
+ return GetRecord<T>();
+ }
+
+ /// <inheritdoc/>
+ public virtual object? GetRecord(Type type)
+ {
+ CheckHasBeenRead();
+
+ if (headerRecord == null && hasHeaderRecord)
+ {
+ ReadHeader();
+ ValidateHeader(type);
+
+ if (!Read())
+ {
+ return null;
+ }
+ }
+
+ object record;
+ try
+ {
+ record = recordManager.Value.Create(type);
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ record = default;
+ }
+
+ return record;
+ }
+
+ /// <inheritdoc/>
+ public virtual IEnumerable<T> GetRecords<T>()
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException(nameof(CsvReader),
+ "GetRecords<T>() returns an IEnumerable<T> that yields records. This means that the method isn't actually called until " +
+ "you try and access the values. e.g. .ToList() Did you create CsvReader inside a using block and are now trying to access " +
+ "the records outside of that using block?"
+ );
+ }
+
+ // Don't need to check if it's been read
+ // since we're doing the reading ourselves.
+
+ if (hasHeaderRecord && headerRecord == null)
+ {
+ if (!Read())
+ {
+ yield break;
+ }
+
+ ReadHeader();
+ ValidateHeader<T>();
+ }
+
+ while (Read())
+ {
+ T record;
+ try
+ {
+ record = recordManager.Value.Create<T>();
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ // If the callback doesn't throw, keep going.
+ continue;
+ }
+
+ yield return record;
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual IEnumerable<T> GetRecords<T>(T anonymousTypeDefinition)
+ {
+ if (anonymousTypeDefinition == null)
+ {
+ throw new ArgumentNullException(nameof(anonymousTypeDefinition));
+ }
+
+ if (!anonymousTypeDefinition.GetType().IsAnonymous())
+ {
+ throw new ArgumentException($"Argument is not an anonymous type.", nameof(anonymousTypeDefinition));
+ }
+
+ return GetRecords<T>();
+ }
+
+ /// <inheritdoc/>
+ public virtual IEnumerable<object?> GetRecords(Type type)
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException(nameof(CsvReader),
+ "GetRecords<object>() returns an IEnumerable<T> that yields records. This means that the method isn't actually called until " +
+ "you try and access the values. e.g. .ToList() Did you create CsvReader inside a using block and are now trying to access " +
+ "the records outside of that using block?"
+ );
+ }
+
+ // Don't need to check if it's been read
+ // since we're doing the reading ourselves.
+
+ if (hasHeaderRecord && headerRecord == null)
+ {
+ if (!Read())
+ {
+ yield break;
+ }
+
+ ReadHeader();
+ ValidateHeader(type);
+ }
+
+ while (Read())
+ {
+ object? record;
+ try
+ {
+ record = recordManager.Value.Create(type);
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ // If the callback doesn't throw, keep going.
+ continue;
+ }
+
+ yield return record;
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual IEnumerable<T> EnumerateRecords<T>(T record)
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException(nameof(CsvReader),
+ "GetRecords<T>() returns an IEnumerable<T> that yields records. This means that the method isn't actually called until " +
+ "you try and access the values. e.g. .ToList() Did you create CsvReader inside a using block and are now trying to access " +
+ "the records outside of that using block?"
+ );
+ }
+
+ // Don't need to check if it's been read
+ // since we're doing the reading ourselves.
+
+ if (hasHeaderRecord && headerRecord == null)
+ {
+ if (!Read())
+ {
+ yield break;
+ }
+
+ ReadHeader();
+ ValidateHeader<T>();
+ }
+
+ while (Read())
+ {
+ try
+ {
+ recordManager.Value.Hydrate(record);
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ // If the callback doesn't throw, keep going.
+ continue;
+ }
+
+ yield return record;
+ }
+ }
+
+#if !NET45
+ /// <inheritdoc/>
+ public virtual async IAsyncEnumerable<T> GetRecordsAsync<T>([EnumeratorCancellation] CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException(nameof(CsvReader),
+ "GetRecords<T>() returns an IEnumerable<T> that yields records. This means that the method isn't actually called until " +
+ "you try and access the values. Did you create CsvReader inside a using block and are now trying to access " +
+ "the records outside of that using block?"
+ );
+ }
+
+ // Don't need to check if it's been read
+ // since we're doing the reading ourselves.
+
+ if (hasHeaderRecord && headerRecord == null)
+ {
+ if (!await ReadAsync().ConfigureAwait(false))
+ {
+ yield break;
+ }
+
+ ReadHeader();
+ ValidateHeader<T>();
+ }
+
+ while (await ReadAsync().ConfigureAwait(false))
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ T record;
+ try
+ {
+ record = recordManager.Value.Create<T>();
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ // If the callback doesn't throw, keep going.
+ continue;
+ }
+
+ yield return record;
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual IAsyncEnumerable<T> GetRecordsAsync<T>(T anonymousTypeDefinition, CancellationToken cancellationToken = default)
+ {
+ if (anonymousTypeDefinition == null)
+ {
+ throw new ArgumentNullException(nameof(anonymousTypeDefinition));
+ }
+
+ if (!anonymousTypeDefinition.GetType().IsAnonymous())
+ {
+ throw new ArgumentException($"Argument is not an anonymous type.", nameof(anonymousTypeDefinition));
+ }
+
+ return GetRecordsAsync<T>(cancellationToken);
+ }
+
+ /// <inheritdoc/>
+ public virtual async IAsyncEnumerable<object?> GetRecordsAsync(Type type, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException(nameof(CsvReader),
+ "GetRecords<object>() returns an IEnumerable<T> that yields records. This means that the method isn't actually called until " +
+ "you try and access the values. Did you create CsvReader inside a using block and are now trying to access " +
+ "the records outside of that using block?"
+ );
+ }
+
+ // Don't need to check if it's been read
+ // since we're doing the reading ourselves.
+
+ if (hasHeaderRecord && headerRecord == null)
+ {
+ if (!await ReadAsync().ConfigureAwait(false))
+ {
+ yield break;
+ }
+
+ ReadHeader();
+ ValidateHeader(type);
+ }
+
+ while (await ReadAsync().ConfigureAwait(false))
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ object record;
+ try
+ {
+ record = recordManager.Value.Create(type);
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ // If the callback doesn't throw, keep going.
+ continue;
+ }
+
+ yield return record;
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual async IAsyncEnumerable<T> EnumerateRecordsAsync<T>(T record, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException(nameof(CsvReader),
+ "GetRecords<T>() returns an IEnumerable<T> that yields records. This means that the method isn't actually called until " +
+ "you try and access the values. Did you create CsvReader inside a using block and are now trying to access " +
+ "the records outside of that using block?"
+ );
+ }
+
+ // Don't need to check if it's been read
+ // since we're doing the reading ourselves.
+
+ if (hasHeaderRecord && headerRecord == null)
+ {
+ if (!await ReadAsync().ConfigureAwait(false))
+ {
+ yield break;
+ }
+
+ ReadHeader();
+ ValidateHeader<T>();
+ }
+
+ while (await ReadAsync().ConfigureAwait(false))
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ try
+ {
+ recordManager.Value.Hydrate(record);
+ }
+ catch (Exception ex)
+ {
+ var csvHelperException = ex as CsvHelperException ?? new ReaderException(context, "An unexpected error occurred.", ex);
+
+ var args = new ReadingExceptionOccurredArgs(csvHelperException);
+ if (readingExceptionOccurred?.Invoke(args) ?? true)
+ {
+ if (ex is CsvHelperException)
+ {
+ throw;
+ }
+ else
+ {
+ throw csvHelperException;
+ }
+ }
+
+ // If the callback doesn't throw, keep going.
+ continue;
+ }
+
+ yield return record;
+ }
+ }
+#endif
+
+ /// <summary>
+ /// Gets the index of the field with the given name.
+ /// </summary>
+ /// <param name="name">The name of the field.</param>
+ /// <param name="index">The index of the field.</param>
+ /// <param name="isTryGet">Indicates if a TryGet is executed.</param>
+ /// <returns>The index of the field.</returns>
+ public virtual int GetFieldIndex(string name, int index = 0, bool isTryGet = false)
+ {
+ return GetFieldIndex(new[] { name }, index, isTryGet);
+ }
+
+ /// <summary>
+ /// Gets the index of the field with the given name.
+ /// </summary>
+ /// <param name="names">The names of the field.</param>
+ /// <param name="index">The index of the field.</param>
+ /// <param name="isTryGet">Indicates if a TryGet is executed.</param>
+ /// <param name="isOptional">Indicates if the field is optional.</param>
+ /// <returns>The index of the field.</returns>
+ public virtual int GetFieldIndex(IEnumerable<string> names, int index = 0, bool isTryGet = false, bool isOptional = false)
+ {
+ if (names == null)
+ {
+ throw new ArgumentNullException(nameof(names));
+ }
+
+ if (!hasHeaderRecord)
+ {
+ throw new ReaderException(context, "There is no header record to determine the index by name.");
+ }
+
+ if (headerRecord == null)
+ {
+ throw new ReaderException(context, "The header has not been read. You must call ReadHeader() before any fields can be retrieved by name.");
+ }
+
+ // Caching the named index speeds up mappings that use ConvertUsing tremendously.
+ var nameKey = string.Join("_", names) + index;
+ if (namedIndexCache.TryGetValue(nameKey, out var cache))
+ {
+ (var cachedName, var cachedIndex) = cache;
+ return namedIndexes[cachedName][cachedIndex];
+ }
+
+ // Check all possible names for this field.
+ string name = null;
+ var i = 0;
+ foreach (var n in names)
+ {
+ // Get the list of indexes for this name.
+ var args = new PrepareHeaderForMatchArgs(n, i);
+ var fieldName = prepareHeaderForMatch(args);
+ if (namedIndexes.ContainsKey(fieldName))
+ {
+ name = fieldName;
+ break;
+ }
+
+ i++;
+ }
+
+ // Check if the index position exists.
+ if (name == null || index >= namedIndexes[name].Count)
+ {
+ // It doesn't exist. The field is missing.
+ if (!isTryGet && !isOptional)
+ {
+ var args = new MissingFieldFoundArgs(names.ToArray(), index, context);
+ missingFieldFound?.Invoke(args);
+ }
+
+ return -1;
+ }
+
+ namedIndexCache.Add(nameKey, (name, index));
+
+ return namedIndexes[name][index];
+ }
+
+ /// <summary>
+ /// Indicates if values can be read.
+ /// </summary>
+ /// <param name="memberMap">The member map.</param>
+ /// <returns>True if values can be read.</returns>
+ public virtual bool CanRead(MemberMap memberMap)
+ {
+ var cantRead =
+ // Ignored member;
+ memberMap.Data.Ignore;
+
+ var property = memberMap.Data.Member as PropertyInfo;
+ if (property != null)
+ {
+ cantRead = cantRead ||
+ // Properties that don't have a public setter
+ // and we are honoring the accessor modifier.
+ property.GetSetMethod() == null && !includePrivateMembers ||
+ // Properties that don't have a setter at all.
+ property.GetSetMethod(true) == null;
+ }
+
+ return !cantRead;
+ }
+
+ /// <summary>
+ /// Indicates if values can be read.
+ /// </summary>
+ /// <param name="memberReferenceMap">The member reference map.</param>
+ /// <returns>True if values can be read.</returns>
+ public virtual bool CanRead(MemberReferenceMap memberReferenceMap)
+ {
+ var cantRead = false;
+
+ var property = memberReferenceMap.Data.Member as PropertyInfo;
+ if (property != null)
+ {
+ cantRead =
+ // Properties that don't have a public setter
+ // and we are honoring the accessor modifier.
+ property.GetSetMethod() == null && !includePrivateMembers ||
+ // Properties that don't have a setter at all.
+ property.GetSetMethod(true) == null;
+ }
+
+ return !cantRead;
+ }
+
+ /// <inheritdoc/>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Disposes the object.
+ /// </summary>
+ /// <param name="disposing">Indicates if the object is being disposed.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ // Dispose managed state (managed objects)
+ if (disposing)
+ {
+ parser.Dispose();
+ }
+
+ // Free unmanaged resources (unmanaged objects) and override finalizer
+ // Set large fields to null
+ context = null;
+
+ disposed = true;
+ }
+
+ /// <summary>
+ /// Checks if the file has been read.
+ /// </summary>
+ /// <exception cref="ReaderException">Thrown when the file has not yet been read.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected virtual void CheckHasBeenRead()
+ {
+ if (!hasBeenRead)
+ {
+ throw new ReaderException(context, "You must call read on the reader before accessing its data.");
+ }
+ }
+
+ /// <summary>
+ /// Parses the named indexes.
+ /// </summary>
+ /// <exception cref="ReaderException">Thrown when no header record was found.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected virtual void ParseNamedIndexes()
+ {
+ if (headerRecord == null)
+ {
+ throw new ReaderException(context, "No header record was found.");
+ }
+
+ namedIndexes.Clear();
+ namedIndexCache.Clear();
+
+ for (var i = 0; i < headerRecord.Length; i++)
+ {
+ var args = new PrepareHeaderForMatchArgs(headerRecord[i], i);
+ var name = prepareHeaderForMatch(args);
+ if (namedIndexes.TryGetValue(name, out var index))
+ {
+ index.Add(i);
+ }
+ else
+ {
+ namedIndexes[name] = new List<int> { i };
+ }
+ }
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/CsvWriter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvWriter.cs
new file mode 100644
index 0000000..4120926
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvWriter.cs
@@ -0,0 +1,842 @@
+// Copyright 2009-2022 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;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using CsvHelper.Configuration;
+using CsvHelper.TypeConversion;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Dynamic;
+using System.Threading.Tasks;
+using CsvHelper.Expressions;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Buffers;
+using System.Threading;
+
+#pragma warning disable 649
+#pragma warning disable 169
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Used to write CSV files.
+ /// </summary>
+ public class CsvWriter : IWriter
+ {
+ private readonly TextWriter writer;
+ private readonly CsvContext context;
+ private readonly Lazy<RecordManager> recordManager;
+ private readonly TypeConverterCache typeConverterCache;
+ private readonly TrimOptions trimOptions;
+ private readonly ShouldQuote shouldQuote;
+ private readonly MemberMapData reusableMemberMapData = new MemberMapData(null);
+ private readonly Dictionary<Type, TypeConverterOptions> typeConverterOptionsCache = new Dictionary<Type, TypeConverterOptions>();
+ private readonly string quoteString;
+ private readonly char quote;
+ private readonly CultureInfo cultureInfo;
+ private readonly char comment;
+ private readonly bool hasHeaderRecord;
+ private readonly bool includePrivateMembers;
+ private readonly IComparer<string> dynamicPropertySort;
+ private readonly string delimiter;
+ private readonly bool leaveOpen;
+ private readonly string newLine;
+ private readonly char[] injectionCharacters;
+ private readonly char injectionEscapeCharacter;
+ private readonly InjectionOptions injectionOptions;
+ private readonly CsvMode mode;
+ private readonly string escapeString;
+ private readonly string escapeQuoteString;
+ private readonly string escapeDelimiterString;
+ private readonly string escapeNewlineString;
+ private readonly string escapeEscapeString;
+
+ private bool disposed;
+ private bool hasHeaderBeenWritten;
+ private int row = 1;
+ private int index;
+ private char[] buffer;
+ private int bufferSize;
+ private int bufferPosition;
+ private Type fieldType;
+
+ /// <inheritdoc/>
+ public virtual string[] HeaderRecord { get; private set; }
+
+ /// <inheritdoc/>
+ public virtual int Row => row;
+
+ /// <inheritdoc/>
+ public virtual int Index => index;
+
+ /// <inheritdoc/>
+ public virtual CsvContext Context => context;
+
+ /// <inheritdoc/>
+ public virtual IWriterConfiguration Configuration { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvWriter"/> class.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ /// <param name="culture">The culture.</param>
+ /// <param name="leaveOpen"><c>true</c> to leave the <see cref="TextWriter"/> open after the <see cref="CsvWriter"/> object is disposed, otherwise <c>false</c>.</param>
+ public CsvWriter(TextWriter writer, CultureInfo culture, bool leaveOpen = false) : this(writer, new CsvConfiguration(culture), leaveOpen) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CsvWriter"/> class.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ /// <param name="configuration">The configuration.</param>
+ /// <param name="leaveOpen"><c>true</c> to leave the <see cref="TextWriter"/> open after the <see cref="CsvWriter"/> object is disposed, otherwise <c>false</c>.</param>
+ public CsvWriter(TextWriter writer, IWriterConfiguration configuration, bool leaveOpen = false)
+ {
+ configuration.Validate();
+
+ this.writer = writer;
+ Configuration = configuration;
+ context = new CsvContext(this);
+ typeConverterCache = context.TypeConverterCache;
+ recordManager = new Lazy<RecordManager>(() => ObjectResolver.Current.Resolve<RecordManager>(this));
+
+ comment = configuration.Comment;
+ bufferSize = configuration.BufferSize;
+ delimiter = configuration.Delimiter;
+ cultureInfo = configuration.CultureInfo;
+ dynamicPropertySort = configuration.DynamicPropertySort;
+ escapeDelimiterString = new string(configuration.Delimiter.SelectMany(c => new[] { configuration.Escape, c }).ToArray());
+ escapeNewlineString = new string(configuration.NewLine.SelectMany(c => new[] { configuration.Escape, c }).ToArray());
+ escapeQuoteString = new string(new[] { configuration.Escape, configuration.Quote });
+ escapeEscapeString = new string(new[] { configuration.Escape, configuration.Escape });
+ hasHeaderRecord = configuration.HasHeaderRecord;
+ includePrivateMembers = configuration.IncludePrivateMembers;
+ injectionCharacters = configuration.InjectionCharacters;
+ injectionEscapeCharacter = configuration.InjectionEscapeCharacter;
+ this.leaveOpen = leaveOpen;
+ mode = configuration.Mode;
+ newLine = configuration.NewLine;
+ quote = configuration.Quote;
+ quoteString = configuration.Quote.ToString();
+ escapeString = configuration.Escape.ToString();
+ injectionOptions = configuration.InjectionOptions;
+ shouldQuote = configuration.ShouldQuote;
+ trimOptions = configuration.TrimOptions;
+
+ buffer = new char[bufferSize];
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteConvertedField(string field, Type fieldType)
+ {
+ this.fieldType = fieldType;
+
+ if (field == null)
+ {
+ return;
+ }
+
+ WriteField(field);
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteField(string field)
+ {
+ if (field != null && (trimOptions & TrimOptions.Trim) == TrimOptions.Trim)
+ {
+ field = field.Trim();
+ }
+
+ fieldType ??= typeof(string);
+
+ var args = new ShouldQuoteArgs(field, fieldType, this);
+ var shouldQuoteResult = shouldQuote(args);
+
+ WriteField(field, shouldQuoteResult);
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteField(string field, bool shouldQuote)
+ {
+ if (mode == CsvMode.RFC4180)
+ {
+ // All quotes must be escaped.
+ if (shouldQuote)
+ {
+ if (escapeString != quoteString)
+ {
+ field = field?.Replace(escapeString, escapeEscapeString);
+ }
+
+ field = field?.Replace(quoteString, escapeQuoteString);
+ field = quote + field + quote;
+ }
+ }
+ else if (mode == CsvMode.Escape)
+ {
+ field = field?
+ .Replace(escapeString, escapeEscapeString)
+ .Replace(quoteString, escapeQuoteString)
+ .Replace(delimiter, escapeDelimiterString)
+ .Replace(newLine, escapeNewlineString);
+ }
+
+ if (injectionOptions != InjectionOptions.None)
+ {
+ field = SanitizeForInjection(field);
+ }
+
+ if (index > 0)
+ {
+ WriteToBuffer(delimiter);
+ }
+
+ WriteToBuffer(field);
+ index++;
+ fieldType = null;
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteField<T>(T field)
+ {
+ var type = field == null ? typeof(string) : field.GetType();
+ var converter = typeConverterCache.GetConverter(type);
+ WriteField(field, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteField<T>(T field, ITypeConverter converter)
+ {
+ var type = field == null ? typeof(string) : field.GetType();
+ reusableMemberMapData.TypeConverter = converter;
+ if (!typeConverterOptionsCache.TryGetValue(type, out TypeConverterOptions typeConverterOptions))
+ {
+ typeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions { CultureInfo = cultureInfo }, context.TypeConverterOptionsCache.GetOptions(type));
+ typeConverterOptionsCache.Add(type, typeConverterOptions);
+ }
+
+ reusableMemberMapData.TypeConverterOptions = typeConverterOptions;
+
+ var fieldString = converter.ConvertToString(field, this, reusableMemberMapData);
+
+ WriteConvertedField(fieldString, type);
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteField<T, TConverter>(T field)
+ {
+ var converter = typeConverterCache.GetConverter<TConverter>();
+
+ WriteField(field, converter);
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteComment(string text)
+ {
+ WriteField(comment + text, false);
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteHeader<T>()
+ {
+ WriteHeader(typeof(T));
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteHeader(Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ if (type == typeof(object))
+ {
+ return;
+ }
+
+ if (context.Maps[type] == null)
+ {
+ context.Maps.Add(context.AutoMap(type));
+ }
+
+ var members = new MemberMapCollection();
+ members.AddMembers(context.Maps[type]);
+
+ var headerRecord = new List<string>();
+
+ foreach (var member in members)
+ {
+ if (CanWrite(member))
+ {
+ if (member.Data.IndexEnd >= member.Data.Index)
+ {
+ var count = member.Data.IndexEnd - member.Data.Index + 1;
+ for (var i = 1; i <= count; i++)
+ {
+ var header = member.Data.Names.FirstOrDefault() + i;
+ WriteField(header);
+ headerRecord.Add(header);
+ }
+ }
+ else
+ {
+ var header = member.Data.Names.FirstOrDefault();
+ WriteField(header);
+ headerRecord.Add(header);
+ }
+ }
+ }
+
+ HeaderRecord = headerRecord.ToArray();
+
+ hasHeaderBeenWritten = true;
+ }
+
+ /// <summary>
+ /// Writes a dynamic header record.
+ /// </summary>
+ /// <param name="record">The header record to write.</param>
+ /// <exception cref="ArgumentNullException">Thrown when no record is passed.</exception>
+ public virtual void WriteDynamicHeader(IDynamicMetaObjectProvider record)
+ {
+ if (record == null)
+ {
+ throw new ArgumentNullException(nameof(record));
+ }
+
+ var metaObject = record.GetMetaObject(Expression.Constant(record));
+ var names = metaObject.GetDynamicMemberNames().ToList();
+ if (dynamicPropertySort != null)
+ {
+ names = names.OrderBy(name => name, dynamicPropertySort).ToList();
+ }
+
+ HeaderRecord = names.ToArray();
+
+ foreach (var name in names)
+ {
+ WriteField(name);
+ }
+
+ hasHeaderBeenWritten = true;
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteRecord<T>(T? record)
+ {
+ try
+ {
+ recordManager.Value.Write(record);
+ }
+ catch (TargetInvocationException ex)
+ {
+ if (ex.InnerException != null)
+ {
+ throw ex.InnerException;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ catch (Exception ex) when (ex is not CsvHelperException)
+ {
+ throw new WriterException(context, "An unexpected error occurred. See inner exception for details.", ex);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteRecords(IEnumerable records)
+ {
+ // Changes in this method require changes in method WriteRecords<T>(IEnumerable<T> records) also.
+
+ try
+ {
+ if (WriteHeader(records))
+ {
+ NextRecord();
+ }
+
+ foreach (var record in records)
+ {
+ if (record == null)
+ {
+ // Since every record could be a different type, just write a blank line.
+ NextRecord();
+ continue;
+ }
+
+ WriteRecord(record);
+ NextRecord();
+ }
+ }
+ catch (Exception ex) when (ex is not CsvHelperException)
+ {
+ throw new WriterException(context, "An unexpected error occurred. See inner exception for details.", ex);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual void WriteRecords<T>(IEnumerable<T> records)
+ {
+ // Changes in this method require changes in method WriteRecords(IEnumerable records) also.
+
+ try
+ {
+ if (WriteHeader(records))
+ {
+ NextRecord();
+ }
+
+ foreach (var record in records)
+ {
+ WriteRecord(record);
+ NextRecord();
+ }
+ }
+ catch (Exception ex) when (ex is not CsvHelperException)
+ {
+ throw new WriterException(context, "An unexpected error occurred. See inner exception for details.", ex);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual async Task WriteRecordsAsync(IEnumerable records, CancellationToken cancellationToken = default)
+ {
+ // These methods should all be the same;
+ // - WriteRecordsAsync(IEnumerable records)
+ // - WriteRecordsAsync<T>(IEnumerable<T> records)
+ // - WriteRecordsAsync<T>(IAsyncEnumerable<T> records)
+
+ try
+ {
+ if (WriteHeader(records))
+ {
+ await NextRecordAsync().ConfigureAwait(false);
+ }
+
+ foreach (var record in records)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ WriteRecord(record);
+ await NextRecordAsync().ConfigureAwait(false);
+ }
+ }
+ catch (Exception ex) when (ex is not CsvHelperException)
+ {
+ throw new WriterException(context, "An unexpected error occurred. See inner exception for details.", ex);
+ }
+ }
+
+ /// <inheritdoc/>
+ public virtual async Task WriteRecordsAsync<T>(IEnumerable<T> records, CancellationToken cancellationToken = default)
+ {
+ // These methods should all be the same;
+ // - WriteRecordsAsync(IEnumerable records)
+ // - WriteRecordsAsync<T>(IEnumerable<T> records)
+ // - WriteRecordsAsync<T>(IAsyncEnumerable<T> records)
+
+ try
+ {
+ if (WriteHeader(records))
+ {
+ await NextRecordAsync().ConfigureAwait(false);
+ }
+
+ foreach (var record in records)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ WriteRecord(record);
+ await NextRecordAsync().ConfigureAwait(false);
+ }
+ }
+ catch (Exception ex) when (ex is not CsvHelperException)
+ {
+ throw new WriterException(context, "An unexpected error occurred. See inner exception for details.", ex);
+ }
+ }
+
+#if !NET45
+ /// <inheritdoc/>
+ public virtual async Task WriteRecordsAsync<T>(IAsyncEnumerable<T> records, CancellationToken cancellationToken = default)
+ {
+ // These methods should all be the same;
+ // - WriteRecordsAsync(IEnumerable records)
+ // - WriteRecordsAsync<T>(IEnumerable<T> records)
+ // - WriteRecordsAsync<T>(IAsyncEnumerable<T> records)
+
+ try
+ {
+ if (await WriteHeaderAsync(records))
+ {
+ await NextRecordAsync().ConfigureAwait(false);
+ }
+
+ await foreach (var record in records.ConfigureAwait(false))
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ WriteRecord(record);
+ await NextRecordAsync().ConfigureAwait(false);
+ }
+ }
+ catch (Exception ex) when (ex is not CsvHelperException)
+ {
+ throw new WriterException(context, "An unexpected error occurred. See inner exception for details.", ex);
+ }
+ }
+#endif
+
+ /// <inheritdoc/>
+ public virtual void NextRecord()
+ {
+ WriteToBuffer(newLine);
+ FlushBuffer();
+
+ index = 0;
+ row++;
+ }
+
+ /// <inheritdoc/>
+ public virtual async Task NextRecordAsync()
+ {
+ WriteToBuffer(newLine);
+ await FlushBufferAsync().ConfigureAwait(false);
+
+ index = 0;
+ row++;
+ }
+
+ /// <inheritdoc/>
+ public virtual void Flush()
+ {
+ FlushBuffer();
+ writer.Flush();
+ }
+
+ /// <inheritdoc/>
+ public virtual async Task FlushAsync()
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ await writer.FlushAsync().ConfigureAwait(false);
+ }
+
+ /// <summary>
+ /// Flushes the buffer.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected virtual void FlushBuffer()
+ {
+ writer.Write(buffer, 0, bufferPosition);
+ bufferPosition = 0;
+ }
+
+ /// <summary>
+ /// Asynchronously flushes the buffer.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected virtual async Task FlushBufferAsync()
+ {
+ await writer.WriteAsync(buffer, 0, bufferPosition).ConfigureAwait(false);
+ bufferPosition = 0;
+ }
+
+ /// <summary>
+ /// Indicates if values can be written.
+ /// </summary>
+ /// <param name="memberMap">The member map.</param>
+ /// <returns>True if values can be written.</returns>
+ public virtual bool CanWrite(MemberMap memberMap)
+ {
+ var cantWrite =
+ // Ignored members.
+ memberMap.Data.Ignore;
+
+ if (memberMap.Data.Member is PropertyInfo property)
+ {
+ cantWrite = cantWrite ||
+ // Properties that don't have a public getter
+ // and we are honoring the accessor modifier.
+ property.GetGetMethod() == null && !includePrivateMembers ||
+ // Properties that don't have a getter at all.
+ property.GetGetMethod(true) == null;
+ }
+
+ return !cantWrite;
+ }
+
+ /// <summary>
+ /// Determines the type for the given record.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ /// <param name="record">The record to determine the type of.</param>
+ /// <returns>The System.Type for the record.</returns>
+ public virtual Type GetTypeForRecord<T>(T record)
+ {
+ var type = typeof(T);
+ if (type == typeof(object))
+ {
+ type = record.GetType();
+ }
+
+ return type;
+ }
+
+ /// <summary>
+ /// Sanitizes the given field, before it is injected.
+ /// </summary>
+ /// <param name="field">The field to sanitize.</param>
+ /// <returns>The sanitized field.</returns>
+ /// <exception cref="WriterException">Thrown when an injection character is found in the field.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected virtual string SanitizeForInjection(string field)
+ {
+ if (string.IsNullOrEmpty(field))
+ {
+ return field;
+ }
+
+ int injectionCharIndex;
+ if (ArrayHelper.Contains(injectionCharacters, field[0]))
+ {
+ injectionCharIndex = 0;
+ }
+ else if (field[0] == quote && field[field.Length - 1] == quote && ArrayHelper.Contains(injectionCharacters, field[1]))
+ {
+ injectionCharIndex = 1;
+ }
+ else
+ {
+ return field;
+ }
+
+ if (injectionOptions == InjectionOptions.Exception)
+ {
+ throw new WriterException(context, $"Injection character '{field[injectionCharIndex]}' detected");
+ }
+
+ if (injectionOptions == InjectionOptions.Escape)
+ {
+ if (injectionCharIndex == 0)
+ {
+ // =1+"2 -> "'=1+""2"
+ field = quoteString + injectionEscapeCharacter + field.Replace(quoteString, escapeQuoteString) + quoteString;
+ }
+ else
+ {
+ // "=1+2" -> "'=1+2"
+ field = quoteString + injectionEscapeCharacter + field.Substring(injectionCharIndex);
+ }
+ }
+ else if (injectionOptions == InjectionOptions.Strip)
+ {
+ while (true)
+ {
+ field = field.Substring(1);
+
+ if (field.Length == 0 || !ArrayHelper.Contains(injectionCharacters, field[0]))
+ {
+ break;
+ }
+ }
+
+ if (injectionCharIndex == 1)
+ {
+ field = quoteString + field;
+ }
+ }
+
+ return field;
+ }
+
+ /// <summary>
+ /// Writes the given value to the buffer.
+ /// </summary>
+ /// <param name="value">The value to write.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected void WriteToBuffer(string value)
+ {
+ var length = value?.Length ?? 0;
+
+ if (value == null || length == 0)
+ {
+ return;
+ }
+
+ var lengthNeeded = bufferPosition + length;
+ if (lengthNeeded >= bufferSize)
+ {
+ while (lengthNeeded >= bufferSize)
+ {
+ bufferSize *= 2;
+ }
+
+ Array.Resize(ref buffer, bufferSize);
+ }
+
+ value.CopyTo(0, buffer, bufferPosition, length);
+
+ bufferPosition += length;
+ }
+
+ /// <inheritdoc/>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Disposes the object.
+ /// </summary>
+ /// <param name="disposing">Indicates if the object is being disposed.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ Flush();
+
+ if (disposing)
+ {
+ // Dispose managed state (managed objects)
+
+ if (!leaveOpen)
+ {
+ writer.Dispose();
+ }
+ }
+
+ // Free unmanaged resources (unmanaged objects) and override finalizer
+ // Set large fields to null
+
+ buffer = null;
+
+ disposed = true;
+ }
+
+#if !NET45 && !NET47 && !NETSTANDARD2_0
+ /// <inheritdoc/>
+ public async ValueTask DisposeAsync()
+ {
+ await DisposeAsync(true).ConfigureAwait(false);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <inheritdoc/>
+ protected virtual async ValueTask DisposeAsync(bool disposing)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ await FlushAsync().ConfigureAwait(false);
+
+ if (disposing)
+ {
+ // Dispose managed state (managed objects)
+
+ if (!leaveOpen)
+ {
+ await writer.DisposeAsync().ConfigureAwait(false);
+ }
+ }
+
+ // Free unmanaged resources (unmanaged objects) and override finalizer
+ // Set large fields to null
+
+ buffer = null;
+
+ disposed = true;
+ }
+#endif
+
+#if !NET45
+ private async Task<bool> WriteHeaderAsync<T>(IAsyncEnumerable<T> records)
+ {
+ if (!hasHeaderRecord || hasHeaderBeenWritten)
+ {
+ return false;
+ }
+
+ var recordType = typeof(T);
+ var isPrimitive = recordType.GetTypeInfo().IsPrimitive;
+ if (!isPrimitive && recordType != typeof(object))
+ {
+ WriteHeader(recordType);
+ return hasHeaderBeenWritten;
+ }
+
+ return WriteHeader(await records.FirstOrDefaultAsync());
+ }
+#endif
+
+ private bool WriteHeader<T>(IEnumerable<T> records)
+ {
+ if (!hasHeaderRecord || hasHeaderBeenWritten)
+ {
+ return false;
+ }
+
+ var recordType = typeof(T);
+ var isPrimitive = recordType.GetTypeInfo().IsPrimitive;
+ if (!isPrimitive && recordType != typeof(object))
+ {
+ WriteHeader(recordType);
+ return hasHeaderBeenWritten;
+ }
+
+ return WriteHeader(records.FirstOrDefault());
+ }
+
+ private bool WriteHeader(IEnumerable records)
+ {
+ object? record = null;
+ foreach (var r in records)
+ {
+ if (r != null)
+ {
+ record = r;
+ }
+ }
+
+ return WriteHeader(record);
+ }
+
+ private bool WriteHeader(object? record)
+ {
+ if (record == null)
+ {
+ return false;
+ }
+
+ if (record is IDynamicMetaObjectProvider dynamicObject)
+ {
+ WriteDynamicHeader(dynamicObject);
+ return true;
+ }
+
+ var recordType = record.GetType();
+ var isPrimitive = recordType.GetTypeInfo().IsPrimitive;
+ if (!isPrimitive)
+ {
+ WriteHeader(recordType);
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/BadDataFound.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/BadDataFound.cs
new file mode 100644
index 0000000..5f25912
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/BadDataFound.cs
@@ -0,0 +1,52 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that gets called when bad data is found.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ public delegate void BadDataFound(BadDataFoundArgs args);
+
+ /// <summary>
+ /// Information about the field that caused <see cref="BadDataFound"/> to be called.
+ /// </summary>
+ public readonly struct BadDataFoundArgs
+ {
+ /// <summary>
+ /// The full field unedited.
+ /// </summary>
+ public readonly string Field;
+
+ /// <summary>
+ /// The full row unedited.
+ /// </summary>
+ public readonly string RawRecord;
+
+ /// <summary>
+ /// The context.
+ /// </summary>
+ public readonly CsvContext Context;
+
+ /// <summary>
+ /// Creates a new instance of BadDataFoundArgs.
+ /// </summary>
+ /// <param name="field">The full field unedited.</param>
+ /// <param name="rawRecord">The full row unedited.</param>
+ /// <param name="context">The context.</param>
+ public BadDataFoundArgs(string field, string rawRecord, CsvContext context)
+ {
+ Field = field;
+ RawRecord = rawRecord;
+ Context = context;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertFromString.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertFromString.cs
new file mode 100644
index 0000000..48b2512
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertFromString.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that converts a string into an object.
+ /// </summary>
+ /// <typeparam name="TMember">The type of the member.</typeparam>
+ /// <param name="args">The args.</param>
+ /// <returns>The class object.</returns>
+ public delegate TMember ConvertFromString<TMember>(ConvertFromStringArgs args);
+
+ /// <summary>
+ /// <see cref="ConvertFromString{TMember}"/> args.
+ /// </summary>
+ public readonly struct ConvertFromStringArgs
+ {
+ /// <summary>
+ /// The row.
+ /// </summary>
+ public readonly IReaderRow Row;
+
+ /// <summary>
+ /// Creates a new instance of ConvertFromStringArgs.
+ /// </summary>
+ /// <param name="row">The row.</param>
+ public ConvertFromStringArgs(IReaderRow row)
+ {
+ Row = row;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertToString.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertToString.cs
new file mode 100644
index 0000000..478526e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertToString.cs
@@ -0,0 +1,41 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that converts an object into a string.
+ /// </summary>
+ /// <typeparam name="TClass">The type of the class.</typeparam>
+ /// <param name="args">The args.</param>
+ /// <returns>The string.</returns>
+ public delegate string ConvertToString<TClass>(ConvertToStringArgs<TClass> args);
+
+ /// <summary>
+ /// <see cref="ConvertToString{TClass}"/> args.
+ /// </summary>
+ /// <typeparam name="TClass">The value to convert.</typeparam>
+ public readonly struct ConvertToStringArgs<TClass>
+ {
+ /// <summary>
+ /// The value to convert.
+ /// </summary>
+ public readonly TClass Value;
+
+ /// <summary>
+ /// Creates a new instance of ConvertToStringArgs{TClass}.
+ /// </summary>
+ /// <param name="value">The value to convert.</param>
+ public ConvertToStringArgs(TClass value)
+ {
+ Value = value;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetConstructor.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetConstructor.cs
new file mode 100644
index 0000000..8678a5c
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetConstructor.cs
@@ -0,0 +1,38 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that chooses the constructor to use for constructor mapping.
+ /// </summary>
+ public delegate ConstructorInfo GetConstructor(GetConstructorArgs args);
+
+ /// <summary>
+ /// GetConstructor args.
+ /// </summary>
+ public readonly struct GetConstructorArgs
+ {
+ /// <summary>
+ /// The class type.
+ /// </summary>
+ public readonly Type ClassType;
+
+ /// <summary>
+ /// Creates a new instance of GetConstructorArgs.
+ /// </summary>
+ /// <param name="classType">The class type.</param>
+ public GetConstructorArgs(Type classType)
+ {
+ ClassType = classType;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDelimiter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDelimiter.cs
new file mode 100644
index 0000000..2593200
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDelimiter.cs
@@ -0,0 +1,44 @@
+using CsvHelper.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.Delegates
+{
+ /// <summary>
+ /// Function that resolves the delimiter from the given text.
+ /// Returns null if no delimiter is found.
+ /// </summary>
+ /// <param name="args"></param>
+ /// <returns></returns>
+ public delegate string? GetDelimiter(GetDelimiterArgs args);
+
+ /// <summary>
+ /// GetDelimiter args.
+ /// </summary>
+ public readonly struct GetDelimiterArgs
+ {
+ /// <summary>
+ /// The text to resolve the delimiter from.
+ /// </summary>
+ public readonly string Text;
+
+ /// <summary>
+ /// The configuration.
+ /// </summary>
+ public readonly IParserConfiguration Configuration;
+
+ /// <summary>
+ /// Creates an instance of GetDelimiterArgs.
+ /// </summary>
+ /// <param name="text">The text to resolve the delimiter from.</param>
+ /// <param name="configuration">The configuration.</param>
+ public GetDelimiterArgs(string text, IParserConfiguration configuration)
+ {
+ Text = text;
+ Configuration = configuration;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDynamicPropertyName.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDynamicPropertyName.cs
new file mode 100644
index 0000000..4a761d6
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDynamicPropertyName.cs
@@ -0,0 +1,44 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that gets the name to use for the property of the dynamic object.
+ /// </summary>
+ public delegate string GetDynamicPropertyName(GetDynamicPropertyNameArgs args);
+
+ /// <summary>
+ /// GetDynamicPropertyName args.
+ /// </summary>
+ public readonly struct GetDynamicPropertyNameArgs
+ {
+ /// <summary>
+ /// The field index.
+ /// </summary>
+ public readonly int FieldIndex;
+
+ /// <summary>
+ /// The context.
+ /// </summary>
+ public readonly CsvContext Context;
+
+ /// <summary>
+ /// Creates a new instance of GetDynamicPropertyNameArgs.
+ /// </summary>
+ /// <param name="fieldIndex">The field index.</param>
+ /// <param name="context">The context.</param>
+ public GetDynamicPropertyNameArgs(int fieldIndex, CsvContext context)
+ {
+ FieldIndex = fieldIndex;
+ Context = context;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/HeaderValidated.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/HeaderValidated.cs
new file mode 100644
index 0000000..07836d3
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/HeaderValidated.cs
@@ -0,0 +1,46 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that is called when a header validation check is ran. The default function
+ /// will throw a <see cref="ValidationException"/> 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.
+ /// </summary>
+ public delegate void HeaderValidated(HeaderValidatedArgs args);
+
+ /// <summary>
+ /// HeaderValidated args.
+ /// </summary>
+ public readonly struct HeaderValidatedArgs
+ {
+ /// <summary>
+ /// The invalid headers.
+ /// </summary>
+ public readonly InvalidHeader[] InvalidHeaders;
+
+ /// <summary>
+ /// The context.
+ /// </summary>
+ public readonly CsvContext Context;
+
+ /// <summary>
+ /// Creates a new instance of HeaderValidatedArgs.
+ /// </summary>
+ /// <param name="invalidHeaders">The invalid headers.</param>
+ /// <param name="context">The context.</param>
+ public HeaderValidatedArgs(InvalidHeader[] invalidHeaders, CsvContext context)
+ {
+ InvalidHeaders = invalidHeaders;
+ Context = context;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/MissingFieldFound.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/MissingFieldFound.cs
new file mode 100644
index 0000000..cb725fb
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/MissingFieldFound.cs
@@ -0,0 +1,53 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that is called when a missing field is found. The default function will
+ /// throw a <see cref="MissingFieldException"/>. You can supply your own function to do other things
+ /// like logging the issue instead of throwing an exception.
+ /// </summary>
+ public delegate void MissingFieldFound(MissingFieldFoundArgs args);
+
+ /// <summary>
+ /// MissingFieldFound args.
+ /// </summary>
+ public readonly struct MissingFieldFoundArgs
+ {
+ /// <summary>
+ /// The header names.
+ /// </summary>
+ public readonly string[]? HeaderNames;
+
+ /// <summary>
+ /// The index.
+ /// </summary>
+ public readonly int Index;
+
+ /// <summary>
+ /// The context.
+ /// </summary>
+ public readonly CsvContext Context;
+
+ /// <summary>
+ /// Creates a new instance of MissingFieldFoundArgs.
+ /// </summary>
+ /// <param name="headerNames">The header names.</param>
+ /// <param name="index">The index.</param>
+ /// <param name="context">The context.</param>
+ public MissingFieldFoundArgs(string[]? headerNames, int index, CsvContext context)
+ {
+ HeaderNames = headerNames;
+ Index = index;
+ Context = context;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/PrepareHeaderForMatch.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/PrepareHeaderForMatch.cs
new file mode 100644
index 0000000..061e493
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/PrepareHeaderForMatch.cs
@@ -0,0 +1,47 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that 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.
+ /// </summary>
+ public delegate string PrepareHeaderForMatch(PrepareHeaderForMatchArgs args);
+
+ /// <summary>
+ /// PrepareHeaderForMatch args.
+ /// </summary>
+ public readonly struct PrepareHeaderForMatchArgs
+ {
+ /// <summary>
+ /// The header.
+ /// </summary>
+ public readonly string Header;
+
+ /// <summary>
+ /// The field index.
+ /// </summary>
+ public readonly int FieldIndex;
+
+ /// <summary>
+ /// Creates a new instance of PrepareHeaderForMatchArgs.
+ /// </summary>
+ /// <param name="header">The header.</param>
+ /// <param name="fieldIndex">The field index.</param>
+ public PrepareHeaderForMatchArgs(string header, int fieldIndex)
+ {
+ Header = header;
+ FieldIndex = fieldIndex;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReadingExceptionOccurred.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReadingExceptionOccurred.cs
new file mode 100644
index 0000000..c3737ef
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReadingExceptionOccurred.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// 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.
+ /// </summary>
+ public delegate bool ReadingExceptionOccurred(ReadingExceptionOccurredArgs args);
+
+ /// <summary>
+ /// ReadingExceptionOccurred args.
+ /// </summary>
+ public readonly struct ReadingExceptionOccurredArgs
+ {
+ /// <summary>
+ /// The exception.
+ /// </summary>
+ public readonly CsvHelperException Exception;
+
+ /// <summary>
+ /// Creates a new instance of ReadingExceptionOccurredArgs.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ public ReadingExceptionOccurredArgs(CsvHelperException exception)
+ {
+ Exception = exception;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReferenceHeaderPrefix.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReferenceHeaderPrefix.cs
new file mode 100644
index 0000000..d42d49f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReferenceHeaderPrefix.cs
@@ -0,0 +1,44 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that will return the prefix for a reference header.
+ /// </summary>
+ public delegate string ReferenceHeaderPrefix(ReferenceHeaderPrefixArgs args);
+
+ /// <summary>
+ /// ReferenceHeaderPrefix args.
+ /// </summary>
+ public readonly struct ReferenceHeaderPrefixArgs
+ {
+ /// <summary>
+ /// The member type.
+ /// </summary>
+ public readonly Type MemberType;
+
+ /// <summary>
+ /// The member name.
+ /// </summary>
+ public readonly string MemberName;
+
+ /// <summary>
+ /// Creates a new instance of ReferenceHeaderPrefixArgs.
+ /// </summary>
+ /// <param name="memberType">The member type.</param>
+ /// <param name="memberName">The member name.</param>
+ public ReferenceHeaderPrefixArgs(Type memberType, string memberName)
+ {
+ MemberType = memberType;
+ MemberName = memberName;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldQuote.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldQuote.cs
new file mode 100644
index 0000000..ab84ba3
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldQuote.cs
@@ -0,0 +1,51 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that is used to determine if a field should get quoted when writing.
+ /// </summary>
+ public delegate bool ShouldQuote(ShouldQuoteArgs args);
+
+ /// <summary>
+ /// ShouldQuote args.
+ /// </summary>
+ public readonly struct ShouldQuoteArgs
+ {
+ /// <summary>
+ /// The field.
+ /// </summary>
+ public readonly string Field;
+
+ /// <summary>
+ /// The field type.
+ /// </summary>
+ public readonly Type FieldType;
+
+ /// <summary>
+ /// The row.
+ /// </summary>
+ public readonly IWriterRow Row;
+
+ /// <summary>
+ /// Creates a new instance of ShouldQuoteArgs.
+ /// </summary>
+ /// <param name="field">The field.</param>
+ /// <param name="fieldType">The field type.</param>
+ /// <param name="row">The row.</param>
+ public ShouldQuoteArgs(string field, Type fieldType, IWriterRow row)
+ {
+ Field = field;
+ FieldType = fieldType;
+ Row = row;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldSkipRecord.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldSkipRecord.cs
new file mode 100644
index 0000000..cf87633
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldSkipRecord.cs
@@ -0,0 +1,37 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that determines whether to skip the given record or not.
+ /// </summary>
+ public delegate bool ShouldSkipRecord(ShouldSkipRecordArgs args);
+
+ /// <summary>
+ /// ShouldSkipRecord args.
+ /// </summary>
+ public readonly struct ShouldSkipRecordArgs
+ {
+ /// <summary>
+ /// The record.
+ /// </summary>
+ public readonly IReaderRow Row;
+
+ /// <summary>
+ /// Creates a new instance of ShouldSkipRecordArgs.
+ /// </summary>
+ /// <param name="row">The row.</param>
+ public ShouldSkipRecordArgs(IReaderRow row)
+ {
+ Row = row;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldUseConstructorParameters.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldUseConstructorParameters.cs
new file mode 100644
index 0000000..cfbacd5
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldUseConstructorParameters.cs
@@ -0,0 +1,38 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that determines if constructor parameters should be used to create
+ /// the class instead of the default constructor and members.
+ /// </summary>
+ public delegate bool ShouldUseConstructorParameters(ShouldUseConstructorParametersArgs args);
+
+ /// <summary>
+ /// ShouldUseConstructorParameters args.
+ /// </summary>
+ public readonly struct ShouldUseConstructorParametersArgs
+ {
+ /// <summary>
+ /// The parameter type.
+ /// </summary>
+ public readonly Type ParameterType;
+
+ /// <summary>
+ /// Creates a new instance of ShouldUseConstructorParametersArgs.
+ /// </summary>
+ /// <param name="parameterType">The parameter type.</param>
+ public ShouldUseConstructorParametersArgs(Type parameterType)
+ {
+ ParameterType = parameterType;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/Validate.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/Validate.cs
new file mode 100644
index 0000000..b2a42ea
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/Validate.cs
@@ -0,0 +1,53 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Function that validates a field.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns><c>true</c> if the field is valid, otherwise <c>false</c>.</returns>
+ public delegate bool Validate(ValidateArgs args);
+
+ /// <summary>
+ /// Function that gets the exception message when validation fails.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns>The exception message.</returns>
+ public delegate string ValidateMessage(ValidateArgs args);
+
+ /// <summary>
+ /// Validate args.
+ /// </summary>
+ public readonly struct ValidateArgs
+ {
+ /// <summary>
+ /// The field.
+ /// </summary>
+ public readonly string Field;
+
+ /// <summary>
+ /// The row.
+ /// </summary>
+ public readonly IReaderRow Row;
+
+ /// <summary>
+ /// Creates a new instance of ValidateArgs.
+ /// </summary>
+ /// <param name="field">The field.</param>
+ /// <param name="row">The row.</param>
+ public ValidateArgs(string field, IReaderRow row)
+ {
+ Field = field;
+ Row = row;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/EnumerableExtensions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/EnumerableExtensions.cs
new file mode 100644
index 0000000..a15b20b
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/EnumerableExtensions.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ internal static class EnumerableExtensions
+ {
+#if !NET45
+ public static async Task<T?> FirstOrDefaultAsync<T>(this IAsyncEnumerable<T> collection)
+ {
+ await foreach (var o in collection.ConfigureAwait(false))
+ {
+ if (o != null)
+ {
+ return o;
+ }
+ }
+
+ return default(T);
+ }
+#endif
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordCreator.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordCreator.cs
new file mode 100644
index 0000000..b93390f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordCreator.cs
@@ -0,0 +1,61 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Dynamic;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Creates dynamic records.
+ /// </summary>
+ public class DynamicRecordCreator : RecordCreator
+ {
+ /// <summary>
+ /// Initializes a new instance.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public DynamicRecordCreator(CsvReader reader) : base(reader) { }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Func{T}"/>
+ /// that will create a record of the given type using the current
+ /// reader row.
+ /// </summary>
+ /// <param name="recordType">The record type.</param>
+ protected override Delegate CreateCreateRecordDelegate(Type recordType) => (Func<dynamic>)CreateDynamicRecord;
+
+ /// <summary>
+ /// Creates a dynamic record of the current reader row.
+ /// </summary>
+ protected virtual dynamic CreateDynamicRecord()
+ {
+ var obj = new ExpandoObject();
+ var dict = obj as IDictionary<string, object>;
+ if (Reader.HeaderRecord != null)
+ {
+ for (var i = 0; i < Reader.HeaderRecord.Length; i++)
+ {
+ var args = new GetDynamicPropertyNameArgs(i, Reader.Context);
+ var propertyName = Reader.Configuration.GetDynamicPropertyName(args);
+ Reader.TryGetField(i, out string field);
+ dict.Add(propertyName, field);
+ }
+ }
+ else
+ {
+ for (var i = 0; i < Reader.Parser.Count; i++)
+ {
+ var args = new GetDynamicPropertyNameArgs(i, Reader.Context);
+ var propertyName = Reader.Configuration.GetDynamicPropertyName(args);
+ var field = Reader.GetField(i);
+ dict.Add(propertyName, field);
+ }
+ }
+
+ return obj;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordWriter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordWriter.cs
new file mode 100644
index 0000000..a9ee401
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordWriter.cs
@@ -0,0 +1,75 @@
+// Copyright 2009-2022 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 Microsoft.CSharp.RuntimeBinder;
+using System;
+using System.Collections;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Write dynamic records.
+ /// </summary>
+ public class DynamicRecordWriter : RecordWriter
+ {
+ private readonly Hashtable getters = new Hashtable();
+
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public DynamicRecordWriter(CsvWriter writer) : base(writer) { }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Action{T}"/>
+ /// that will write the given record using the current writer row.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <param name="record">The record.</param>
+ protected override Action<T> CreateWriteDelegate<T>(T record)
+ {
+ // http://stackoverflow.com/a/14011692/68499
+
+ Action<T> action = r =>
+ {
+ var provider = (IDynamicMetaObjectProvider)r;
+ var type = provider.GetType();
+
+ var parameterExpression = Expression.Parameter(typeof(T), "record");
+ var metaObject = provider.GetMetaObject(parameterExpression);
+ var memberNames = metaObject.GetDynamicMemberNames();
+ if (Writer.Configuration.DynamicPropertySort != null)
+ {
+ memberNames = memberNames.OrderBy(name => name, Writer.Configuration.DynamicPropertySort);
+ }
+
+ foreach (var name in memberNames)
+ {
+ var value = GetValue(name, provider);
+ Writer.WriteField(value);
+ }
+ };
+
+ return action;
+ }
+
+ private object GetValue(string name, IDynamicMetaObjectProvider target)
+ {
+ // https://stackoverflow.com/a/30757547/68499
+
+ var callSite = (CallSite<Func<CallSite, IDynamicMetaObjectProvider, object>>)getters[name];
+ if (callSite == null)
+ {
+ var getMemberBinder = Binder.GetMember(CSharpBinderFlags.None, name, typeof(DynamicRecordWriter), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
+ getters[name] = callSite = CallSite<Func<CallSite, IDynamicMetaObjectProvider, object>>.Create(getMemberBinder);
+ }
+
+ return callSite.Target(callSite, target);
+ }
+ }
+} \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs
new file mode 100644
index 0000000..f0a5e67
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs
@@ -0,0 +1,49 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Writes expando objects.
+ /// </summary>
+ public class ExpandoObjectRecordWriter : RecordWriter
+ {
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public ExpandoObjectRecordWriter(CsvWriter writer) : base(writer) { }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Action{T}"/>
+ /// that will write the given record using the current writer row.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <param name="record">The record.</param>
+ protected override Action<T> CreateWriteDelegate<T>(T record)
+ {
+ Action<T> action = r =>
+ {
+ var dict = ((IDictionary<string, object>)r).AsEnumerable();
+
+ if (Writer.Configuration.DynamicPropertySort != null)
+ {
+ dict = dict.OrderBy(pair => pair.Key, Writer.Configuration.DynamicPropertySort);
+ }
+
+ var values = dict.Select(pair => pair.Value);
+ foreach (var val in values)
+ {
+ Writer.WriteField(val);
+ }
+ };
+
+ return action;
+ }
+ }
+} \ No newline at end of file
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpressionManager.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpressionManager.cs
new file mode 100644
index 0000000..42ac8a6
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpressionManager.cs
@@ -0,0 +1,490 @@
+// Copyright 2009-2022 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;
+using CsvHelper.TypeConversion;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Manages expression creation.
+ /// </summary>
+ public class ExpressionManager
+ {
+ private readonly CsvReader reader;
+ private readonly CsvWriter writer;
+
+ /// <summary>
+ /// Initializes a new instance using the given reader.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public ExpressionManager(CsvReader reader)
+ {
+ this.reader = reader;
+ }
+
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public ExpressionManager(CsvWriter writer)
+ {
+ this.writer = writer;
+ }
+
+ /// <summary>
+ /// Creates the constructor arguments used to create a type.
+ /// </summary>
+ /// <param name="map">The mapping to create the arguments for.</param>
+ /// <param name="argumentExpressions">The arguments that will be added to the mapping.</param>
+ public virtual void CreateConstructorArgumentExpressionsForMapping(ClassMap map, List<Expression> argumentExpressions)
+ {
+ foreach (var parameterMap in map.ParameterMaps)
+ {
+ if (parameterMap.Data.IsConstantSet)
+ {
+ var constantExpression = Expression.Convert(Expression.Constant(parameterMap.Data.Constant), parameterMap.Data.Parameter.ParameterType);
+ argumentExpressions.Add(constantExpression);
+
+ continue;
+ }
+
+ if (parameterMap.Data.Ignore)
+ {
+ Expression defaultExpression;
+ if (parameterMap.Data.IsDefaultSet)
+ {
+ defaultExpression = Expression.Convert(Expression.Constant(parameterMap.Data.Default), parameterMap.Data.Parameter.ParameterType);
+ }
+ else if (parameterMap.Data.Parameter.HasDefaultValue)
+ {
+ defaultExpression = Expression.Convert(Expression.Constant(parameterMap.Data.Parameter.DefaultValue), parameterMap.Data.Parameter.ParameterType);
+ }
+ else
+ {
+ defaultExpression = Expression.Default(parameterMap.Data.Parameter.ParameterType);
+ }
+
+ argumentExpressions.Add(defaultExpression);
+
+ continue;
+ }
+
+ if (parameterMap.ConstructorTypeMap != null)
+ {
+ // Constructor parameter type.
+ var arguments = new List<Expression>();
+ CreateConstructorArgumentExpressionsForMapping(parameterMap.ConstructorTypeMap, arguments);
+ var args = new GetConstructorArgs(parameterMap.ConstructorTypeMap.ClassType);
+ var constructorExpression = Expression.New(reader.Configuration.GetConstructor(args), arguments);
+
+ argumentExpressions.Add(constructorExpression);
+ }
+ else if (parameterMap.ReferenceMap != null)
+ {
+ // Reference type.
+
+ var referenceAssignments = new List<MemberAssignment>();
+ CreateMemberAssignmentsForMapping(parameterMap.ReferenceMap.Data.Mapping, referenceAssignments);
+
+ var referenceBody = CreateInstanceAndAssignMembers(parameterMap.ReferenceMap.Data.Parameter.ParameterType, referenceAssignments);
+ argumentExpressions.Add(referenceBody);
+ }
+ else
+ {
+ // Value type.
+
+ int index;
+ if (reader.Configuration.HasHeaderRecord && (parameterMap.Data.IsNameSet || !parameterMap.Data.IsIndexSet))
+ {
+ // Use name.
+ index = reader.GetFieldIndex(parameterMap.Data.Names, parameterMap.Data.NameIndex, parameterMap.Data.IsOptional);
+ if (index == -1)
+ {
+ if (parameterMap.Data.IsDefaultSet || parameterMap.Data.IsOptional)
+ {
+ var defaultExpression = CreateDefaultExpression(parameterMap, Expression.Constant(string.Empty));
+ argumentExpressions.Add(defaultExpression);
+ continue;
+ }
+
+ // Skip if the index was not found.
+ continue;
+ }
+ }
+ else if (!parameterMap.Data.IsIndexSet && parameterMap.Data.IsOptional)
+ {
+ // If there wasn't an index explicitly, use a default value since constructors need all
+ // arguments to be created.
+ var defaultExpression = CreateDefaultExpression(parameterMap, Expression.Constant(string.Empty));
+ argumentExpressions.Add(defaultExpression);
+ continue;
+ }
+ else
+ {
+ // Use index.
+ index = parameterMap.Data.Index;
+ }
+
+ // Get the field using the field index.
+ var method = typeof(IReaderRow).GetProperty("Item", typeof(string), new[] { typeof(int) }).GetGetMethod();
+ Expression fieldExpression = Expression.Call(Expression.Constant(reader), method, Expression.Constant(index, typeof(int)));
+
+ if (parameterMap.Data.IsDefaultSet)
+ {
+ fieldExpression = CreateDefaultExpression(parameterMap, fieldExpression);
+ }
+ else
+ {
+ fieldExpression = CreateTypeConverterExpression(parameterMap, fieldExpression);
+ }
+
+ argumentExpressions.Add(fieldExpression);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates the member assignments for the given <see cref="ClassMap"/>.
+ /// </summary>
+ /// <param name="mapping">The mapping to create the assignments for.</param>
+ /// <param name="assignments">The assignments that will be added to from the mapping.</param>
+ public virtual void CreateMemberAssignmentsForMapping(ClassMap mapping, List<MemberAssignment> assignments)
+ {
+ foreach (var memberMap in mapping.MemberMaps)
+ {
+ var fieldExpression = CreateGetFieldExpression(memberMap);
+ if (fieldExpression == null)
+ {
+ continue;
+ }
+
+ assignments.Add(Expression.Bind(memberMap.Data.Member, fieldExpression));
+ }
+
+ foreach (var referenceMap in mapping.ReferenceMaps)
+ {
+ if (!reader.CanRead(referenceMap))
+ {
+ continue;
+ }
+
+ Expression referenceBody;
+ if (referenceMap.Data.Mapping.ParameterMaps.Count > 0)
+ {
+ var arguments = new List<Expression>();
+ CreateConstructorArgumentExpressionsForMapping(referenceMap.Data.Mapping, arguments);
+ var args = new GetConstructorArgs(referenceMap.Data.Mapping.ClassType);
+ referenceBody = Expression.New(reader.Configuration.GetConstructor(args), arguments);
+ }
+ else
+ {
+ var referenceAssignments = new List<MemberAssignment>();
+ CreateMemberAssignmentsForMapping(referenceMap.Data.Mapping, referenceAssignments);
+ referenceBody = CreateInstanceAndAssignMembers(referenceMap.Data.Member.MemberType(), referenceAssignments);
+ }
+
+ assignments.Add(Expression.Bind(referenceMap.Data.Member, referenceBody));
+ }
+ }
+
+ /// <summary>
+ /// Creates an expression the represents getting the field for the given
+ /// member and converting it to the member's type.
+ /// </summary>
+ /// <param name="memberMap">The mapping for the member.</param>
+ public virtual Expression? CreateGetFieldExpression(MemberMap memberMap)
+ {
+ if (memberMap.Data.ReadingConvertExpression != null)
+ {
+ // The user is providing the expression to do the conversion.
+ Expression exp = Expression.Invoke(memberMap.Data.ReadingConvertExpression, Expression.Constant(new ConvertFromStringArgs(reader)));
+ return Expression.Convert(exp, memberMap.Data.Member.MemberType());
+ }
+
+ if (!reader.CanRead(memberMap))
+ {
+ return null;
+ }
+
+ if (memberMap.Data.IsConstantSet)
+ {
+ return Expression.Convert(Expression.Constant(memberMap.Data.Constant), memberMap.Data.Member.MemberType());
+ }
+
+ if (memberMap.Data.TypeConverter == null)
+ {
+ // Skip if the type isn't convertible.
+ return null;
+ }
+
+ int index;
+ if (reader.Configuration.HasHeaderRecord && (memberMap.Data.IsNameSet || !memberMap.Data.IsIndexSet))
+ {
+ // Use the name.
+ index = reader.GetFieldIndex(memberMap.Data.Names, memberMap.Data.NameIndex, memberMap.Data.IsOptional);
+ if (index == -1)
+ {
+ if (memberMap.Data.IsDefaultSet)
+ {
+ return CreateDefaultExpression(memberMap, Expression.Constant(string.Empty));
+ }
+
+ // Skip if the index was not found.
+ return null;
+ }
+ }
+ else
+ {
+ // Use the index.
+ index = memberMap.Data.Index;
+ }
+
+ // Get the field using the field index.
+ var method = typeof(IReaderRow).GetProperty("Item", typeof(string), new[] { typeof(int) }).GetGetMethod();
+ Expression fieldExpression = Expression.Call(Expression.Constant(reader), method, Expression.Constant(index, typeof(int)));
+
+ // Validate the field.
+ if (memberMap.Data.ValidateExpression != null)
+ {
+ var constructor = typeof(ValidateArgs).GetConstructor(new Type[] { typeof(string), typeof(IReaderRow) });
+ var args = Expression.New(constructor, fieldExpression, Expression.Constant(reader));
+ var validateExpression = Expression.IsFalse(Expression.Invoke(memberMap.Data.ValidateExpression, args));
+ var validationExceptionConstructor = typeof(FieldValidationException).GetConstructor(new Type[] { typeof(CsvContext), typeof(string), typeof(string) });
+ var messageExpression = Expression.Invoke(memberMap.Data.ValidateMessageExpression, args);
+ var newValidationExceptionExpression = Expression.New(validationExceptionConstructor, Expression.Constant(reader.Context), fieldExpression, messageExpression);
+ var throwExpression = Expression.Throw(newValidationExceptionExpression);
+ fieldExpression = Expression.Block(
+ // If the validate method returns false, throw an exception.
+ Expression.IfThen(validateExpression, throwExpression),
+ fieldExpression
+ );
+ }
+
+ if (memberMap.Data.IsDefaultSet)
+ {
+ return CreateDefaultExpression(memberMap, fieldExpression);
+ }
+
+ fieldExpression = CreateTypeConverterExpression(memberMap, fieldExpression);
+
+ return fieldExpression;
+ }
+
+ /// <summary>
+ /// Creates a member expression for the given member on the record.
+ /// This will recursively traverse the mapping to find the member
+ /// and create a safe member accessor for each level as it goes.
+ /// </summary>
+ /// <param name="recordExpression">The current member expression.</param>
+ /// <param name="mapping">The mapping to look for the member to map on.</param>
+ /// <param name="memberMap">The member map to look for on the mapping.</param>
+ /// <returns>An Expression to access the given member.</returns>
+ public virtual Expression? CreateGetMemberExpression(Expression recordExpression, ClassMap mapping, MemberMap memberMap)
+ {
+ if (mapping.MemberMaps.Any(mm => mm == memberMap))
+ {
+ // The member is on this level.
+ if (memberMap.Data.Member is PropertyInfo)
+ {
+ return Expression.Property(recordExpression, (PropertyInfo)memberMap.Data.Member);
+ }
+
+ if (memberMap.Data.Member is FieldInfo)
+ {
+ return Expression.Field(recordExpression, (FieldInfo)memberMap.Data.Member);
+ }
+ }
+
+ // The member isn't on this level of the mapping.
+ // We need to search down through the reference maps.
+ foreach (var refMap in mapping.ReferenceMaps)
+ {
+ var wrapped = refMap.Data.Member.GetMemberExpression(recordExpression);
+ var memberExpression = CreateGetMemberExpression(wrapped, refMap.Data.Mapping, memberMap);
+ if (memberExpression == null)
+ {
+ continue;
+ }
+
+ if (refMap.Data.Member.MemberType().GetTypeInfo().IsValueType)
+ {
+ return memberExpression;
+ }
+
+ var nullCheckExpression = Expression.Equal(wrapped, Expression.Constant(null));
+
+ var isValueType = memberMap.Data.Member.MemberType().GetTypeInfo().IsValueType;
+ var isGenericType = isValueType && memberMap.Data.Member.MemberType().GetTypeInfo().IsGenericType;
+ Type memberType;
+ if (isValueType && !isGenericType && !writer.Configuration.UseNewObjectForNullReferenceMembers)
+ {
+ memberType = typeof(Nullable<>).MakeGenericType(memberMap.Data.Member.MemberType());
+ memberExpression = Expression.Convert(memberExpression, memberType);
+ }
+ else
+ {
+ memberType = memberMap.Data.Member.MemberType();
+ }
+
+ var defaultValueExpression = isValueType && !isGenericType
+ ? (Expression)Expression.New(memberType)
+ : Expression.Constant(null, memberType);
+ var conditionExpression = Expression.Condition(nullCheckExpression, defaultValueExpression, memberExpression);
+ return conditionExpression;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Creates an instance of the given type using <see cref="IObjectResolver"/>, then assigns
+ /// the given member assignments to that instance.
+ /// </summary>
+ /// <param name="recordType">The type of the record we're creating.</param>
+ /// <param name="assignments">The member assignments that will be assigned to the created instance.</param>
+ /// <returns>A <see cref="BlockExpression"/> representing the instance creation and assignments.</returns>
+ public virtual BlockExpression CreateInstanceAndAssignMembers(Type recordType, List<MemberAssignment> assignments)
+ {
+ var expressions = new List<Expression>();
+ var createInstanceMethod = typeof(IObjectResolver).GetMethod(nameof(IObjectResolver.Resolve), new Type[] { typeof(Type), typeof(object[]) });
+ var instanceExpression = Expression.Convert(Expression.Call(Expression.Constant(ObjectResolver.Current), createInstanceMethod, Expression.Constant(recordType), Expression.Constant(new object[0])), recordType);
+ var variableExpression = Expression.Variable(instanceExpression.Type, "instance");
+ expressions.Add(Expression.Assign(variableExpression, instanceExpression));
+ expressions.AddRange(assignments.Select(b => Expression.Assign(Expression.MakeMemberAccess(variableExpression, b.Member), b.Expression)));
+ expressions.Add(variableExpression);
+ var variables = new ParameterExpression[] { variableExpression };
+ var blockExpression = Expression.Block(variables, expressions);
+
+ return blockExpression;
+ }
+
+ /// <summary>
+ /// Creates an expression that converts the field expression using a type converter.
+ /// </summary>
+ /// <param name="memberMap">The mapping for the member.</param>
+ /// <param name="fieldExpression">The field expression.</param>
+ public virtual Expression CreateTypeConverterExpression(MemberMap memberMap, Expression fieldExpression)
+ {
+ memberMap.Data.TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions { CultureInfo = reader.Configuration.CultureInfo }, reader.Context.TypeConverterOptionsCache.GetOptions(memberMap.Data.Member.MemberType()), memberMap.Data.TypeConverterOptions);
+
+ Expression typeConverterFieldExpression = Expression.Call(Expression.Constant(memberMap.Data.TypeConverter), nameof(ITypeConverter.ConvertFromString), null, fieldExpression, Expression.Constant(reader), Expression.Constant(memberMap.Data));
+ typeConverterFieldExpression = Expression.Convert(typeConverterFieldExpression, memberMap.Data.Member.MemberType());
+
+ return typeConverterFieldExpression;
+ }
+
+ /// <summary>
+ /// Creates an expression that converts the field expression using a type converter.
+ /// </summary>
+ /// <param name="parameterMap">The mapping for the parameter.</param>
+ /// <param name="fieldExpression">The field expression.</param>
+ public virtual Expression CreateTypeConverterExpression(ParameterMap parameterMap, Expression fieldExpression)
+ {
+ parameterMap.Data.TypeConverterOptions = TypeConverterOptions.Merge
+ (
+ new TypeConverterOptions { CultureInfo = reader.Configuration.CultureInfo },
+ reader.Context.TypeConverterOptionsCache.GetOptions(parameterMap.Data.Parameter.ParameterType),
+ parameterMap.Data.TypeConverterOptions
+ );
+
+ var memberMapData = new MemberMapData(null)
+ {
+ Constant = parameterMap.Data.Constant,
+ Default = parameterMap.Data.Default,
+ Ignore = parameterMap.Data.Ignore,
+ Index = parameterMap.Data.Index,
+ IsConstantSet = parameterMap.Data.IsConstantSet,
+ IsDefaultSet = parameterMap.Data.IsDefaultSet,
+ IsIndexSet = parameterMap.Data.IsIndexSet,
+ IsNameSet = parameterMap.Data.IsNameSet,
+ NameIndex = parameterMap.Data.NameIndex,
+ TypeConverter = parameterMap.Data.TypeConverter,
+ TypeConverterOptions = parameterMap.Data.TypeConverterOptions
+ };
+ memberMapData.Names.AddRange(parameterMap.Data.Names);
+
+ Expression typeConverterFieldExpression = Expression.Call(Expression.Constant(parameterMap.Data.TypeConverter), nameof(ITypeConverter.ConvertFromString), null, fieldExpression, Expression.Constant(reader), Expression.Constant(memberMapData));
+ typeConverterFieldExpression = Expression.Convert(typeConverterFieldExpression, parameterMap.Data.Parameter.ParameterType);
+
+ return typeConverterFieldExpression;
+ }
+
+ /// <summary>
+ /// Creates a default expression if field expression is empty.
+ /// </summary>
+ /// <param name="memberMap">The mapping for the member.</param>
+ /// <param name="fieldExpression">The field expression.</param>
+ public virtual Expression CreateDefaultExpression(MemberMap memberMap, Expression fieldExpression)
+ {
+ var typeConverterExpression = CreateTypeConverterExpression(memberMap, fieldExpression);
+
+ // Create default value expression.
+ Expression defaultValueExpression;
+ if (memberMap.Data.Member.MemberType() != typeof(string) && memberMap.Data.Default != null && memberMap.Data.Default.GetType() == typeof(string))
+ {
+ // The default is a string but the member type is not. Use a converter.
+ defaultValueExpression = Expression.Call(Expression.Constant(memberMap.Data.TypeConverter), nameof(ITypeConverter.ConvertFromString), null, Expression.Constant(memberMap.Data.Default), Expression.Constant(reader), Expression.Constant(memberMap.Data));
+ }
+ else
+ {
+ // The member type and default type match.
+ defaultValueExpression = Expression.Constant(memberMap.Data.Default);
+ }
+
+ defaultValueExpression = Expression.Convert(defaultValueExpression, memberMap.Data.Member.MemberType());
+
+ // If null, use string.Empty.
+ var coalesceExpression = Expression.Coalesce(fieldExpression, Expression.Constant(string.Empty));
+
+ // Check if the field is an empty string.
+ var checkFieldEmptyExpression = Expression.Equal(Expression.Convert(coalesceExpression, typeof(string)), Expression.Constant(string.Empty, typeof(string)));
+
+ // Use a default value if the field is an empty string.
+ fieldExpression = Expression.Condition(checkFieldEmptyExpression, defaultValueExpression, typeConverterExpression);
+
+ return fieldExpression;
+ }
+
+ /// <summary>
+ /// Creates a default expression if field expression is empty.
+ /// </summary>
+ /// <param name="parameterMap">The mapping for the parameter.</param>
+ /// <param name="fieldExpression">The field expression.</param>
+ public virtual Expression CreateDefaultExpression(ParameterMap parameterMap, Expression fieldExpression)
+ {
+ var typeConverterExpression = CreateTypeConverterExpression(parameterMap, fieldExpression);
+
+ // Create default value expression.
+ Expression defaultValueExpression;
+ if (parameterMap.Data.Parameter.ParameterType != typeof(string) && parameterMap.Data.Default != null && parameterMap.Data.Default.GetType() == typeof(string))
+ {
+ // The default is a string but the member type is not. Use a converter.
+ //defaultValueExpression = Expression.Call(Expression.Constant(parameterMap.Data.TypeConverter), nameof(ITypeConverter.ConvertFromString), null, Expression.Constant(parameterMap.Data.Default), Expression.Constant(reader), Expression.Constant(memberMap.Data));
+ defaultValueExpression = CreateTypeConverterExpression(parameterMap, Expression.Constant(parameterMap.Data.Default));
+ }
+ else
+ {
+ // The member type and default type match.
+ defaultValueExpression = Expression.Convert(Expression.Constant(parameterMap.Data.Default), parameterMap.Data.Parameter.ParameterType);
+ }
+
+ // If null, use string.Empty.
+ var coalesceExpression = Expression.Coalesce(fieldExpression, Expression.Constant(string.Empty));
+
+ // Check if the field is an empty string.
+ var checkFieldEmptyExpression = Expression.Equal(Expression.Convert(coalesceExpression, typeof(string)), Expression.Constant(string.Empty, typeof(string)));
+
+ // Use a default value if the field is an empty string.
+ fieldExpression = Expression.Condition(checkFieldEmptyExpression, defaultValueExpression, typeConverterExpression);
+
+ return fieldExpression;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordCreator.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordCreator.cs
new file mode 100644
index 0000000..9adc951
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordCreator.cs
@@ -0,0 +1,66 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Creates objects.
+ /// </summary>
+ public class ObjectRecordCreator : RecordCreator
+ {
+ /// <summary>
+ /// Initializes a new instance using the given reader.
+ /// </summary>
+ /// <param name="reader"></param>
+ public ObjectRecordCreator(CsvReader reader) : base(reader) { }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Func{T}"/>
+ /// that will create a record of the given type using the current
+ /// reader row.
+ /// </summary>
+ /// <param name="recordType">The record type.</param>
+ protected override Delegate CreateCreateRecordDelegate(Type recordType)
+ {
+ if (Reader.Context.Maps[recordType] == null)
+ {
+ Reader.Context.Maps.Add(Reader.Context.AutoMap(recordType));
+ }
+
+ var map = Reader.Context.Maps[recordType];
+
+ Expression body;
+
+ if (map.ParameterMaps.Count > 0)
+ {
+ // This is a constructor parameter type.
+ var arguments = new List<Expression>();
+ ExpressionManager.CreateConstructorArgumentExpressionsForMapping(map, arguments);
+
+ var args = new GetConstructorArgs(map.ClassType);
+ body = Expression.New(Reader.Configuration.GetConstructor(args), arguments);
+ }
+ else
+ {
+ var assignments = new List<MemberAssignment>();
+ ExpressionManager.CreateMemberAssignmentsForMapping(map, assignments);
+
+ if (assignments.Count == 0)
+ {
+ throw new ReaderException(Reader.Context, $"No members are mapped for type '{recordType.FullName}'.");
+ }
+
+ body = ExpressionManager.CreateInstanceAndAssignMembers(recordType, assignments);
+ }
+
+ var funcType = typeof(Func<>).MakeGenericType(recordType);
+
+ return Expression.Lambda(funcType, body).Compile();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordWriter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordWriter.cs
new file mode 100644
index 0000000..08fc79b
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordWriter.cs
@@ -0,0 +1,124 @@
+// Copyright 2009-2022 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;
+using CsvHelper.TypeConversion;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Writes objects.
+ /// </summary>
+ public class ObjectRecordWriter : RecordWriter
+ {
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public ObjectRecordWriter(CsvWriter writer) : base(writer) { }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Action{T}"/>
+ /// that will write the given record using the current writer row.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <param name="record">The record.</param>
+ protected override Action<T> CreateWriteDelegate<T>(T record)
+ {
+ var type = Writer.GetTypeForRecord(record);
+
+ if (Writer.Context.Maps[type] == null)
+ {
+ Writer.Context.Maps.Add(Writer.Context.AutoMap(type));
+ }
+
+ var recordParameter = Expression.Parameter(typeof(T), "record");
+ var recordParameterConverted = Expression.Convert(recordParameter, type);
+
+ // Get a list of all the members so they will
+ // be sorted properly.
+ var members = new MemberMapCollection();
+ members.AddMembers(Writer.Context.Maps[type]);
+
+ if (members.Count == 0)
+ {
+ throw new WriterException(Writer.Context, $"No properties are mapped for type '{type.FullName}'.");
+ }
+
+ var delegates = new List<Action<T>>();
+
+ foreach (var memberMap in members)
+ {
+ if (memberMap.Data.WritingConvertExpression != null)
+ {
+ // The user is providing the expression to do the conversion.
+ var constructor = typeof(ConvertToStringArgs<T>).GetConstructor(new Type[] { typeof(T) });
+ var args = Expression.New(constructor, recordParameterConverted);
+ Expression exp = Expression.Invoke(memberMap.Data.WritingConvertExpression, args);
+ exp = Expression.Call(Expression.Constant(Writer), nameof(Writer.WriteField), null, exp);
+ delegates.Add(Expression.Lambda<Action<T>>(exp, recordParameter).Compile());
+ continue;
+ }
+
+ if (!Writer.CanWrite(memberMap))
+ {
+ continue;
+ }
+
+ Expression fieldExpression;
+
+ if (memberMap.Data.IsConstantSet)
+ {
+ if (memberMap.Data.Constant == null)
+ {
+ fieldExpression = Expression.Constant(string.Empty);
+ }
+ else
+ {
+ fieldExpression = Expression.Constant(memberMap.Data.Constant);
+ var typeConverterExpression = Expression.Constant(Writer.Context.TypeConverterCache.GetConverter(memberMap.Data.Constant.GetType()));
+ var method = typeof(ITypeConverter).GetMethod(nameof(ITypeConverter.ConvertToString));
+ fieldExpression = Expression.Convert(fieldExpression, typeof(object));
+ fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression, Expression.Constant(Writer), Expression.Constant(memberMap.Data));
+ }
+ }
+ else
+ {
+ if (memberMap.Data.TypeConverter == null)
+ {
+ // Skip if the type isn't convertible.
+ continue;
+ }
+
+ fieldExpression = ExpressionManager.CreateGetMemberExpression(recordParameterConverted, Writer.Context.Maps[type], memberMap);
+
+ var typeConverterExpression = Expression.Constant(memberMap.Data.TypeConverter);
+ memberMap.Data.TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions { CultureInfo = Writer.Configuration.CultureInfo }, Writer.Context.TypeConverterOptionsCache.GetOptions(memberMap.Data.Member.MemberType()), memberMap.Data.TypeConverterOptions);
+
+ var method = typeof(ITypeConverter).GetMethod(nameof(ITypeConverter.ConvertToString));
+ fieldExpression = Expression.Convert(fieldExpression, typeof(object));
+ fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression, Expression.Constant(Writer), Expression.Constant(memberMap.Data));
+
+ if (type.GetTypeInfo().IsClass)
+ {
+ var areEqualExpression = Expression.Equal(recordParameterConverted, Expression.Constant(null));
+ fieldExpression = Expression.Condition(areEqualExpression, Expression.Constant(string.Empty), fieldExpression);
+ }
+ }
+
+ var writeFieldMethodCall = Expression.Call(Expression.Constant(Writer), nameof(Writer.WriteConvertedField), null, fieldExpression, Expression.Constant(memberMap.Data.Type));
+
+ delegates.Add(Expression.Lambda<Action<T>>(writeFieldMethodCall, recordParameter).Compile());
+ }
+
+ var action = CombineDelegates(delegates) ?? new Action<T>((T parameter) => { });
+
+ return action;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordCreator.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordCreator.cs
new file mode 100644
index 0000000..3e1cfd0
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordCreator.cs
@@ -0,0 +1,49 @@
+// Copyright 2009-2022 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;
+using CsvHelper.TypeConversion;
+using System;
+using System.Linq.Expressions;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Creates primitive records.
+ /// </summary>
+ public class PrimitiveRecordCreator : RecordCreator
+ {
+ /// <summary>
+ /// Initializes a new instance using the given reader.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public PrimitiveRecordCreator(CsvReader reader) : base(reader) { }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Func{T}"/>
+ /// that will create a record of the given type using the current
+ /// reader row.
+ /// </summary>
+ /// <param name="recordType">The record type.</param>
+ protected override Delegate CreateCreateRecordDelegate(Type recordType)
+ {
+ var method = typeof(IReaderRow).GetProperty("Item", typeof(string), new[] { typeof(int) }).GetGetMethod();
+ Expression fieldExpression = Expression.Call(Expression.Constant(Reader), method, Expression.Constant(0, typeof(int)));
+
+ var memberMapData = new MemberMapData(null)
+ {
+ Index = 0,
+ TypeConverter = Reader.Context.TypeConverterCache.GetConverter(recordType)
+ };
+ memberMapData.TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions { CultureInfo = Reader.Configuration.CultureInfo }, Reader.Context.TypeConverterOptionsCache.GetOptions(recordType));
+
+ fieldExpression = Expression.Call(Expression.Constant(memberMapData.TypeConverter), "ConvertFromString", null, fieldExpression, Expression.Constant(Reader), Expression.Constant(memberMapData));
+ fieldExpression = Expression.Convert(fieldExpression, recordType);
+
+ var funcType = typeof(Func<>).MakeGenericType(recordType);
+
+ return Expression.Lambda(funcType, fieldExpression).Compile();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordWriter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordWriter.cs
new file mode 100644
index 0000000..128c5c3
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordWriter.cs
@@ -0,0 +1,57 @@
+// Copyright 2009-2022 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;
+using CsvHelper.TypeConversion;
+using System;
+using System.Linq.Expressions;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Writes primitives.
+ /// </summary>
+ public class PrimitiveRecordWriter : RecordWriter
+ {
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public PrimitiveRecordWriter(CsvWriter writer) : base(writer) { }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Action{T}"/>
+ /// that will write the given record using the current writer row.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <param name="record">The record.</param>
+ protected override Action<T> CreateWriteDelegate<T>(T record)
+ {
+ var type = Writer.GetTypeForRecord(record);
+
+ var recordParameter = Expression.Parameter(typeof(T), "record");
+
+ Expression fieldExpression = Expression.Convert(recordParameter, typeof(object));
+
+ var typeConverter = Writer.Context.TypeConverterCache.GetConverter(type);
+ var typeConverterExpression = Expression.Constant(typeConverter);
+ var method = typeof(ITypeConverter).GetMethod(nameof(ITypeConverter.ConvertToString));
+
+ var memberMapData = new MemberMapData(null)
+ {
+ Index = 0,
+ TypeConverter = typeConverter,
+ TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions(), Writer.Context.TypeConverterOptionsCache.GetOptions(type))
+ };
+ memberMapData.TypeConverterOptions.CultureInfo = Writer.Configuration.CultureInfo;
+
+ fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression, Expression.Constant(Writer), Expression.Constant(memberMapData));
+ fieldExpression = Expression.Call(Expression.Constant(Writer), nameof(Writer.WriteConvertedField), null, fieldExpression, Expression.Constant(type));
+
+ var action = Expression.Lambda<Action<T>>(fieldExpression, recordParameter).Compile();
+
+ return action;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreator.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreator.cs
new file mode 100644
index 0000000..d14f0d6
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreator.cs
@@ -0,0 +1,107 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Base implementation for classes that create records.
+ /// </summary>
+ public abstract class RecordCreator
+ {
+ private readonly Dictionary<Type, Delegate> createRecordFuncs = new Dictionary<Type, Delegate>();
+
+ /// <summary>
+ /// The reader.
+ /// </summary>
+ protected CsvReader Reader { get; private set; }
+
+ /// <summary>
+ /// The expression manager.
+ /// </summary>
+ protected ExpressionManager ExpressionManager { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance using the given reader.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public RecordCreator(CsvReader reader)
+ {
+ Reader = reader;
+ ExpressionManager = new ExpressionManager(reader);
+ }
+
+ /// <summary>
+ /// Create a record of the given type using the current row.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ public T Create<T>()
+ {
+ try
+ {
+ return ((Func<T>)GetCreateRecordDelegate(typeof(T))).Invoke();
+ }
+ catch (TargetInvocationException ex)
+ {
+ if (ex.InnerException != null)
+ {
+ throw ex.InnerException;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Create a record of the given type using the current row.
+ /// </summary>
+ /// <param name="recordType">The record type.</param>
+ public object? Create(Type recordType)
+ {
+ try
+ {
+ return GetCreateRecordDelegate(recordType).DynamicInvoke();
+ }
+ catch (TargetInvocationException ex)
+ {
+ if (ex.InnerException != null)
+ {
+ throw ex.InnerException;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the delegate to create a record for the given record type.
+ /// If the delegate doesn't exist, one will be created and cached.
+ /// </summary>
+ /// <param name="recordType">The record type.</param>
+ protected virtual Delegate GetCreateRecordDelegate(Type recordType)
+ {
+ if (!createRecordFuncs.TryGetValue(recordType, out Delegate func))
+ {
+ createRecordFuncs[recordType] = func = CreateCreateRecordDelegate(recordType);
+ }
+
+ return func;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Func{T}"/>
+ /// that will create a record of the given type using the current
+ /// reader row.
+ /// </summary>
+ /// <param name="recordType">The record type.</param>
+ protected abstract Delegate CreateCreateRecordDelegate(Type recordType);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreatorFactory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreatorFactory.cs
new file mode 100644
index 0000000..b785115
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreatorFactory.cs
@@ -0,0 +1,51 @@
+// Copyright 2009-2022 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;
+using System.Reflection;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Factory to create record creators.
+ /// </summary>
+ public class RecordCreatorFactory
+ {
+ private readonly CsvReader reader;
+ private readonly DynamicRecordCreator dynamicRecordCreator;
+ private readonly PrimitiveRecordCreator primitiveRecordCreator;
+ private readonly ObjectRecordCreator objectRecordCreator;
+
+ /// <summary>
+ /// Initializes a new instance using the given reader.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public RecordCreatorFactory(CsvReader reader)
+ {
+ this.reader = reader;
+ dynamicRecordCreator = new DynamicRecordCreator(reader);
+ primitiveRecordCreator = new PrimitiveRecordCreator(reader);
+ objectRecordCreator = new ObjectRecordCreator(reader);
+ }
+
+ /// <summary>
+ /// Creates a record creator for the given record type.
+ /// </summary>
+ /// <param name="recordType">The record type.</param>
+ public virtual RecordCreator MakeRecordCreator(Type recordType)
+ {
+ if (recordType == typeof(object))
+ {
+ return dynamicRecordCreator;
+ }
+
+ if (recordType.GetTypeInfo().IsPrimitive)
+ {
+ return primitiveRecordCreator;
+ }
+
+ return objectRecordCreator;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordHydrator.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordHydrator.cs
new file mode 100644
index 0000000..7de4ddb
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordHydrator.cs
@@ -0,0 +1,126 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Hydrates members of an existing record.
+ /// </summary>
+ public class RecordHydrator
+ {
+ private readonly CsvReader reader;
+ private readonly ExpressionManager expressionManager;
+ private readonly Dictionary<Type, Delegate> hydrateRecordActions = new Dictionary<Type, Delegate>();
+
+ /// <summary>
+ /// Creates a new instance using the given reader.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public RecordHydrator(CsvReader reader)
+ {
+ this.reader = reader;
+ expressionManager = ObjectResolver.Current.Resolve<ExpressionManager>(reader);
+ }
+
+ /// <summary>
+ /// Hydrates members of the given record using the current reader row.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <param name="record">The record.</param>
+ public void Hydrate<T>(T record)
+ {
+ try
+ {
+ GetHydrateRecordAction<T>()(record);
+ }
+ catch (TargetInvocationException ex)
+ {
+ if (ex.InnerException != null)
+ {
+ throw ex.InnerException;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the action delegate used to hydrate a custom class object's members with data from the reader.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ protected virtual Action<T> GetHydrateRecordAction<T>()
+ {
+ var recordType = typeof(T);
+
+ if (!hydrateRecordActions.TryGetValue(recordType, out Delegate action))
+ {
+ hydrateRecordActions[recordType] = action = CreateHydrateRecordAction<T>();
+ }
+
+ return (Action<T>)action;
+ }
+
+ /// <summary>
+ /// Creates the action delegate used to hydrate a record's members with data from the reader.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ protected virtual Action<T> CreateHydrateRecordAction<T>()
+ {
+ var recordType = typeof(T);
+
+ if (reader.Context.Maps[recordType] == null)
+ {
+ reader.Context.Maps.Add(reader.Context.AutoMap(recordType));
+ }
+
+ var mapping = reader.Context.Maps[recordType];
+
+ var recordTypeParameter = Expression.Parameter(recordType, "record");
+ var memberAssignments = new List<Expression>();
+
+ foreach (var memberMap in mapping.MemberMaps)
+ {
+ var fieldExpression = expressionManager.CreateGetFieldExpression(memberMap);
+ if (fieldExpression == null)
+ {
+ continue;
+ }
+
+ var memberTypeParameter = Expression.Parameter(memberMap.Data.Member.MemberType(), "member");
+ var memberAccess = Expression.MakeMemberAccess(recordTypeParameter, memberMap.Data.Member);
+ var memberAssignment = Expression.Assign(memberAccess, fieldExpression);
+ memberAssignments.Add(memberAssignment);
+ }
+
+ foreach (var referenceMap in mapping.ReferenceMaps)
+ {
+ if (!reader.CanRead(referenceMap))
+ {
+ continue;
+ }
+
+ var referenceAssignments = new List<MemberAssignment>();
+ expressionManager.CreateMemberAssignmentsForMapping(referenceMap.Data.Mapping, referenceAssignments);
+
+ var referenceBody = expressionManager.CreateInstanceAndAssignMembers(referenceMap.Data.Member.MemberType(), referenceAssignments);
+
+ var memberTypeParameter = Expression.Parameter(referenceMap.Data.Member.MemberType(), "referenceMember");
+ var memberAccess = Expression.MakeMemberAccess(recordTypeParameter, referenceMap.Data.Member);
+ var memberAssignment = Expression.Assign(memberAccess, referenceBody);
+ memberAssignments.Add(memberAssignment);
+ }
+
+ var body = Expression.Block(memberAssignments);
+
+ return Expression.Lambda<Action<T>>(body, recordTypeParameter).Compile();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordManager.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordManager.cs
new file mode 100644
index 0000000..eef3d6e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordManager.cs
@@ -0,0 +1,80 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Manages record manipulation.
+ /// </summary>
+ public class RecordManager
+ {
+ private readonly CsvReader reader;
+ private readonly RecordCreatorFactory recordCreatorFactory;
+ private readonly RecordHydrator recordHydrator;
+ private readonly RecordWriterFactory recordWriterFactory;
+
+ /// <summary>
+ /// Initializes a new instance using the given reader.
+ /// </summary>
+ /// <param name="reader"></param>
+ public RecordManager(CsvReader reader)
+ {
+ this.reader = reader;
+ recordCreatorFactory = ObjectResolver.Current.Resolve<RecordCreatorFactory>(reader);
+ recordHydrator = ObjectResolver.Current.Resolve<RecordHydrator>(reader);
+ }
+
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public RecordManager(CsvWriter writer)
+ {
+ recordWriterFactory = ObjectResolver.Current.Resolve<RecordWriterFactory>(writer);
+ }
+
+ /// <summary>
+ /// Creates a record of the given type using the current reader row.
+ /// </summary>
+ /// <typeparam name="T">The type of record to create.</typeparam>
+ public T Create<T>()
+ {
+ var recordCreator = recordCreatorFactory.MakeRecordCreator(typeof(T));
+ return recordCreator.Create<T>();
+ }
+
+ /// <summary>
+ /// Creates a record of the given type using the current reader row.
+ /// </summary>
+ /// <param name="recordType">The type of record to create.</param>
+ public object? Create(Type recordType)
+ {
+ var recordCreator = recordCreatorFactory.MakeRecordCreator(recordType);
+ return recordCreator.Create(recordType);
+ }
+
+ /// <summary>
+ /// Hydrates the given record using the current reader row.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ /// <param name="record">The record to hydrate.</param>
+ public void Hydrate<T>(T record)
+ {
+ recordHydrator.Hydrate(record);
+ }
+
+ /// <summary>
+ /// Writes the given record to the current writer row.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ /// <param name="record">The record.</param>
+ public void Write<T>(T record)
+ {
+ var recordWriter = recordWriterFactory.MakeRecordWriter(record);
+ recordWriter.Write(record);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriter.cs
new file mode 100644
index 0000000..ca1194f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriter.cs
@@ -0,0 +1,109 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Base implementation for classes that write records.
+ /// </summary>
+ public abstract class RecordWriter
+ {
+ private readonly Dictionary<int, Delegate> typeActions = new Dictionary<int, Delegate>();
+
+ /// <summary>
+ /// Gets the writer.
+ /// </summary>
+ protected CsvWriter Writer { get; private set; }
+
+ /// <summary>
+ /// The expression manager.
+ /// </summary>
+ protected ExpressionManager ExpressionManager { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public RecordWriter(CsvWriter writer)
+ {
+ Writer = writer;
+ ExpressionManager = ObjectResolver.Current.Resolve<ExpressionManager>(writer);
+ }
+
+ /// <summary>
+ /// Writes the record to the current row.
+ /// </summary>
+ /// <typeparam name="T">Type of the record.</typeparam>
+ /// <param name="record">The record.</param>
+ public void Write<T>(T record)
+ {
+ try
+ {
+ GetWriteDelegate(record)(record);
+ }
+ catch (TargetInvocationException ex)
+ {
+ if (ex.InnerException != null)
+ {
+ throw ex.InnerException;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the delegate to write the given record.
+ /// If the delegate doesn't exist, one will be created and cached.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <param name="record">The record.</param>
+ protected Action<T> GetWriteDelegate<T>(T record)
+ {
+ var type = typeof(T);
+ var typeKeyName = type.AssemblyQualifiedName;
+ if (type == typeof(object))
+ {
+ type = record.GetType();
+ typeKeyName += $"|{type.AssemblyQualifiedName}";
+ }
+
+ int typeKey = typeKeyName.GetHashCode();
+
+ if (!typeActions.TryGetValue(typeKey, out Delegate action))
+ {
+ typeActions[typeKey] = action = CreateWriteDelegate(record);
+ }
+
+ return (Action<T>)action;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="Delegate"/> of type <see cref="Action{T}"/>
+ /// that will write the given record using the current writer row.
+ /// </summary>
+ /// <typeparam name="T">The record type.</typeparam>
+ /// <param name="record">The record.</param>
+ protected abstract Action<T> CreateWriteDelegate<T>(T record);
+
+ /// <summary>
+ /// Combines the delegates into a single multicast delegate.
+ /// This is needed because Silverlight doesn't have the
+ /// Delegate.Combine( params Delegate[] ) overload.
+ /// </summary>
+ /// <param name="delegates">The delegates to combine.</param>
+ /// <returns>A multicast delegate combined from the given delegates.</returns>
+ protected virtual Action<T> CombineDelegates<T>(IEnumerable<Action<T>> delegates)
+ {
+ return (Action<T>)delegates.Aggregate<Delegate, Delegate>(null, Delegate.Combine);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriterFactory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriterFactory.cs
new file mode 100644
index 0000000..4f27001
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriterFactory.cs
@@ -0,0 +1,61 @@
+// Copyright 2009-2022 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.Dynamic;
+using System.Reflection;
+
+namespace CsvHelper.Expressions
+{
+ /// <summary>
+ /// Factory to create record writers.
+ /// </summary>
+ public class RecordWriterFactory
+ {
+ private readonly CsvWriter writer;
+ private readonly ExpandoObjectRecordWriter expandoObjectRecordWriter;
+ private readonly DynamicRecordWriter dynamicRecordWriter;
+ private readonly PrimitiveRecordWriter primitiveRecordWriter;
+ private readonly ObjectRecordWriter objectRecordWriter;
+
+ /// <summary>
+ /// Initializes a new instance using the given writer.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ public RecordWriterFactory(CsvWriter writer)
+ {
+ this.writer = writer;
+ expandoObjectRecordWriter = new ExpandoObjectRecordWriter(writer);
+ dynamicRecordWriter = new DynamicRecordWriter(writer);
+ primitiveRecordWriter = new PrimitiveRecordWriter(writer);
+ objectRecordWriter = new ObjectRecordWriter(writer);
+ }
+
+ /// <summary>
+ /// Creates a new record writer for the given record.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ /// <param name="record">The record.</param>
+ public virtual RecordWriter MakeRecordWriter<T>(T record)
+ {
+ var type = writer.GetTypeForRecord(record);
+
+ if (record is ExpandoObject expandoObject)
+ {
+ return expandoObjectRecordWriter;
+ }
+
+ if (record is IDynamicMetaObjectProvider dynamicObject)
+ {
+ return dynamicRecordWriter;
+ }
+
+ if (type.GetTypeInfo().IsPrimitive)
+ {
+ return primitiveRecordWriter;
+ }
+
+ return objectRecordWriter;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Factory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Factory.cs
new file mode 100644
index 0000000..80db167
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Factory.cs
@@ -0,0 +1,108 @@
+// Copyright 2009-2022 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;
+using System.IO;
+using CsvHelper.Configuration;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Creates CsvHelper classes.
+ /// </summary>
+ public class Factory : IFactory
+ {
+ /// <summary>
+ /// Creates an <see cref="IParser"/>.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv parser.</param>
+ /// <param name="configuration">The configuration to use for the csv parser.</param>
+ /// <returns>The created parser.</returns>
+ public virtual IParser CreateParser(TextReader reader, Configuration.CsvConfiguration configuration)
+ {
+ return new CsvParser(reader, configuration);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IParser" />.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv parser.</param>
+ /// <param name="cultureInfo">The culture information.</param>
+ /// <returns>
+ /// The created parser.
+ /// </returns>
+ public virtual IParser CreateParser(TextReader reader, CultureInfo cultureInfo)
+ {
+ return new CsvParser(reader, cultureInfo);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IReader"/>.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv reader.</param>
+ /// <param name="configuration">The configuration to use for the reader.</param>
+ /// <returns>The created reader.</returns>
+ public virtual IReader CreateReader(TextReader reader, Configuration.CsvConfiguration configuration)
+ {
+ return new CsvReader(reader, configuration);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IReader" />.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv reader.</param>
+ /// <param name="cultureInfo">The culture information.</param>
+ /// <returns>
+ /// The created reader.
+ /// </returns>
+ public virtual IReader CreateReader(TextReader reader, CultureInfo cultureInfo)
+ {
+ return new CsvReader(reader, cultureInfo);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IReader"/>.
+ /// </summary>
+ /// <param name="parser">The parser used to create the reader.</param>
+ /// <returns>The created reader.</returns>
+ public virtual IReader CreateReader(IParser parser)
+ {
+ return new CsvReader(parser);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IWriter"/>.
+ /// </summary>
+ /// <param name="writer">The text writer to use for the csv writer.</param>
+ /// <param name="configuration">The configuration to use for the writer.</param>
+ /// <returns>The created writer.</returns>
+ public virtual IWriter CreateWriter(TextWriter writer, Configuration.CsvConfiguration configuration)
+ {
+ return new CsvWriter(writer, configuration);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IWriter" />.
+ /// </summary>
+ /// <param name="writer">The text writer to use for the csv writer.</param>
+ /// <param name="cultureInfo">The culture information.</param>
+ /// <returns>
+ /// The created writer.
+ /// </returns>
+ public virtual IWriter CreateWriter(TextWriter writer, CultureInfo cultureInfo)
+ {
+ return new CsvWriter(writer, cultureInfo);
+ }
+
+ /// <summary>
+ /// Access point for fluent interface to dynamically build a <see cref="ClassMap{T}"/>
+ /// </summary>
+ /// <typeparam name="T">Type you will be making a class map for</typeparam>
+ /// <returns>Options to further configure the <see cref="ClassMap{T}"/></returns>
+ public IHasMap<T> CreateClassMapBuilder<T>()
+ {
+ return new ClassMapBuilder<T>();
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/FieldCache.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/FieldCache.cs
new file mode 100644
index 0000000..665a650
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/FieldCache.cs
@@ -0,0 +1,137 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+// https://blog.markvincze.com/back-to-basics-dictionary-part-2-net-implementation/
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Caches fields.
+ /// Based on C#'s <see cref="Dictionary{TKey, TValue}"/>.
+ /// </summary>
+ internal class FieldCache
+ {
+ private readonly int maxFieldSize;
+ private int size;
+ private int[] buckets;
+ private Entry[] entries;
+ private int count;
+
+ public FieldCache(int initialSize = 128, int maxFieldSize = 128)
+ {
+ this.maxFieldSize = maxFieldSize;
+ size = initialSize;
+ buckets = new int[size];
+ entries = new Entry[size];
+ }
+
+ public string GetField(char[] buffer, int start, int length)
+ {
+ if (length == 0)
+ {
+ return string.Empty;
+ }
+
+ if (length > maxFieldSize)
+ {
+ return new string(buffer, start, length);
+ }
+
+ var hashCode = GetHashCode(buffer, start, length);
+ ref var bucket = ref GetBucket(hashCode);
+ int i = bucket - 1;
+ while ((uint)i < (uint)entries.Length)
+ {
+ ref var entry = ref entries[i];
+
+ if (entry.HashCode == hashCode && entry.Value.AsSpan().SequenceEqual(new Span<char>(buffer, start, length)))
+ {
+ return entry.Value;
+ }
+
+ i = entry.Next;
+ }
+
+ if (count == entries.Length)
+ {
+ Resize();
+ bucket = ref GetBucket(hashCode);
+ }
+
+ ref var reference = ref entries[count];
+ reference.HashCode = hashCode;
+ reference.Next = bucket - 1;
+ reference.Value = new string(buffer, start, length);
+ bucket = count + 1;
+ count++;
+
+ return reference.Value;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private uint GetHashCode(char[] buffer, int start, int length)
+ {
+ unchecked
+ {
+ uint hash = 17;
+ for (var i = start; i < start + length; i++)
+ {
+ hash = hash * 31 + buffer[i];
+ }
+
+ return hash;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private ref int GetBucket(uint hashCode)
+ {
+ return ref buckets[hashCode & buckets.Length - 1];
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void Resize()
+ {
+ size *= 2;
+
+ var tempEntries = new Entry[size];
+
+ Array.Copy(entries, tempEntries, count);
+
+ buckets = new int[size];
+
+ for (int i = 0; i < count; i++)
+ {
+ ref var tempEntry = ref tempEntries[i];
+
+ if (tempEntry.Next >= -1)
+ {
+ ref var bucket = ref GetBucket(tempEntry.HashCode);
+ tempEntry.Next = bucket - 1;
+ bucket = i + 1;
+ }
+ }
+
+ entries = tempEntries;
+ }
+
+ [DebuggerDisplay("HashCode = {HashCode}, Next = {Next}, Value = {Value}")]
+ private struct Entry
+ {
+ public uint HashCode;
+
+ public int Next;
+
+ public string Value;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/FieldValidationException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/FieldValidationException.cs
new file mode 100644
index 0000000..9f4eacd
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/FieldValidationException.cs
@@ -0,0 +1,55 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents a user supplied field validation failure.
+ /// </summary>
+ public class FieldValidationException : ValidationException
+ {
+ /// <summary>
+ /// Gets the field that failed validation.
+ /// </summary>
+ public string Field { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="field">The field that failed validation.</param>
+ public FieldValidationException(CsvContext context, string field) : base(context)
+ {
+ Field = field;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="field">The field that failed validation.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public FieldValidationException(CsvContext context, string field, string message) : base(context, message)
+ {
+ Field = field;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="field">The field that failed validation.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public FieldValidationException(CsvContext context, string field, string message, Exception innerException) : base(context, message, innerException)
+ {
+ Field = field;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/HeaderValidationException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/HeaderValidationException.cs
new file mode 100644
index 0000000..ded47b8
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/HeaderValidationException.cs
@@ -0,0 +1,55 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents a header validation failure.
+ /// </summary>
+ public class HeaderValidationException : ValidationException
+ {
+ /// <summary>
+ /// Gets the invalid headers.
+ /// </summary>
+ public InvalidHeader[] InvalidHeaders { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="invalidHeaders">The invalid headers.</param>
+ public HeaderValidationException(CsvContext context, InvalidHeader[] invalidHeaders) : base(context)
+ {
+ InvalidHeaders = invalidHeaders;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="invalidHeaders">The invalid headers.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public HeaderValidationException(CsvContext context, InvalidHeader[] invalidHeaders, string message) : base(context, message)
+ {
+ InvalidHeaders = invalidHeaders;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="invalidHeaders">The invalid headers.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public HeaderValidationException(CsvContext context, InvalidHeader[] invalidHeaders, string message, Exception innerException) : base(context, message, innerException)
+ {
+ InvalidHeaders = invalidHeaders;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/IFactory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/IFactory.cs
new file mode 100644
index 0000000..bf857b5
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/IFactory.cs
@@ -0,0 +1,85 @@
+// Copyright 2009-2022 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;
+using System.IO;
+using CsvHelper.Configuration;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Defines methods used to create
+ /// CsvHelper classes.
+ /// </summary>
+ public interface IFactory
+ {
+ /// <summary>
+ /// Creates an <see cref="IParser"/>.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv parser.</param>
+ /// <param name="configuration">The configuration to use for the csv parser.</param>
+ /// <returns>The created parser.</returns>
+ IParser CreateParser(TextReader reader, Configuration.CsvConfiguration configuration);
+
+ /// <summary>
+ /// Creates an <see cref="IParser" />.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv parser.</param>
+ /// <param name="cultureInfo">The culture information.</param>
+ /// <returns>
+ /// The created parser.
+ /// </returns>
+ IParser CreateParser(TextReader reader, CultureInfo cultureInfo);
+
+ /// <summary>
+ /// Creates an <see cref="IReader"/>.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv reader.</param>
+ /// <param name="configuration">The configuration to use for the reader.</param>
+ /// <returns>The created reader.</returns>
+ IReader CreateReader(TextReader reader, Configuration.CsvConfiguration configuration);
+
+ /// <summary>
+ /// Creates an <see cref="IReader" />.
+ /// </summary>
+ /// <param name="reader">The text reader to use for the csv reader.</param>
+ /// <param name="cultureInfo">The culture information.</param>
+ /// <returns>
+ /// The created reader.
+ /// </returns>
+ IReader CreateReader(TextReader reader, CultureInfo cultureInfo);
+
+ /// <summary>
+ /// Creates an <see cref="IReader"/>.
+ /// </summary>
+ /// <param name="parser">The parser used to create the reader.</param>
+ /// <returns>The created reader.</returns>
+ IReader CreateReader(IParser parser);
+
+ /// <summary>
+ /// Creates an <see cref="IWriter"/>.
+ /// </summary>
+ /// <param name="writer">The text writer to use for the csv writer.</param>
+ /// <param name="configuration">The configuration to use for the writer.</param>
+ /// <returns>The created writer.</returns>
+ IWriter CreateWriter(TextWriter writer, Configuration.CsvConfiguration configuration);
+
+ /// <summary>
+ /// Creates an <see cref="IWriter" />.
+ /// </summary>
+ /// <param name="writer">The text writer to use for the csv writer.</param>
+ /// <param name="cultureInfo">The culture information.</param>
+ /// <returns>
+ /// The created writer.
+ /// </returns>
+ IWriter CreateWriter(TextWriter writer, CultureInfo cultureInfo);
+
+ /// <summary>
+ /// Provides a fluent interface for dynamically creating <see cref="ClassMap{T}"/>s
+ /// </summary>
+ /// <typeparam name="T">Type of class to map</typeparam>
+ /// <returns>Next available options</returns>
+ IHasMap<T> CreateClassMapBuilder<T>();
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/IObjectResolver.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/IObjectResolver.cs
new file mode 100644
index 0000000..c419114
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/IObjectResolver.cs
@@ -0,0 +1,57 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Defines the functionality of a class that creates objects
+ /// from a given type.
+ /// </summary>
+ public interface IObjectResolver
+ {
+ /// <summary>
+ /// A value indicating if the resolver's <see cref="CanResolve"/>
+ /// returns false that an object will still be created using
+ /// CsvHelper's object creation. True to fallback, otherwise false.
+ /// Default value is true.
+ /// </summary>
+ bool UseFallback { get; }
+
+ /// <summary>
+ /// A value indicating if the resolver is able to resolve
+ /// the given type. True if the type can be resolved,
+ /// otherwise false.
+ /// </summary>
+ Func<Type, bool> CanResolve { get; }
+
+ /// <summary>
+ /// The function that creates an object from a given type.
+ /// </summary>
+ Func<Type, object[], object> ResolveFunction { get; }
+
+ /// <summary>
+ /// Creates an object from the given type using the <see cref="ResolveFunction"/>
+ /// function. If <see cref="CanResolve"/> is false, the object will be
+ /// created using CsvHelper's default object creation. If <see cref="UseFallback"/>
+ /// is false, an exception is thrown.
+ /// </summary>
+ /// <param name="type">The type to create an instance from. The created object
+ /// may not be the same type as the given type.</param>
+ /// <param name="constructorArgs">Constructor arguments used to create the type.</param>
+ object Resolve( Type type, params object[] constructorArgs );
+
+ /// <summary>
+ /// Creates an object from the given type using the <see cref="ResolveFunction"/>
+ /// function. If <see cref="CanResolve"/> is false, the object will be
+ /// created using CsvHelper's default object creation. If <see cref="UseFallback"/>
+ /// is false, an exception is thrown.
+ /// </summary>
+ /// <typeparam name="T">The type to create an instance from. The created object
+ /// may not be the same type as the given type.</typeparam>
+ /// <param name="constructorArgs">Constructor arguments used to create the type.</param>
+ T Resolve<T>( params object[] constructorArgs );
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/IParser.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/IParser.cs
new file mode 100644
index 0000000..040a701
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/IParser.cs
@@ -0,0 +1,89 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Defines methods used the parse a CSV file.
+ /// </summary>
+ public interface IParser : IDisposable
+ {
+ /// <summary>
+ /// Gets the count of how many bytes have been read.
+ /// <see cref="IParserConfiguration.CountBytes"/> needs
+ /// to be enabled for this value to be populated.
+ /// </summary>
+ long ByteCount { get; }
+
+ /// <summary>
+ /// Gets the count of how many characters have been read.
+ /// </summary>
+ long CharCount { get; }
+
+ /// <summary>
+ /// Gets the number of fields for the current row.
+ /// </summary>
+ int Count { get; }
+
+ /// <summary>
+ /// Gets the field at the specified index for the current row.
+ /// </summary>
+ /// <param name="index">The index.</param>
+ /// <returns>The field.</returns>
+ string this[int index] { get; }
+
+ /// <summary>
+ /// Gets the record for the current row. Note:
+ /// It is much more efficient to only get the fields you need. If
+ /// you need all fields, then use this.
+ /// </summary>
+ string[]? Record { get; }
+
+ /// <summary>
+ /// Gets the raw record for the current row.
+ /// </summary>
+ string RawRecord { get; }
+
+ /// <summary>
+ /// Gets the CSV row the parser is currently on.
+ /// </summary>
+ int Row { get; }
+
+ /// <summary>
+ /// Gets the raw row the parser is currently on.
+ /// </summary>
+ int RawRow { get; }
+
+ /// <summary>
+ /// The delimiter the parser is using.
+ /// </summary>
+ string Delimiter { get; }
+
+ /// <summary>
+ /// Gets the reading context.
+ /// </summary>
+ CsvContext Context { get; }
+
+ /// <summary>
+ /// Gets the configuration.
+ /// </summary>
+ IParserConfiguration Configuration { get; }
+
+ /// <summary>
+ /// Reads a record from the CSV file.
+ /// </summary>
+ /// <returns>True if there are more records to read, otherwise false.</returns>
+ bool Read();
+
+ /// <summary>
+ /// Reads a record from the CSV file asynchronously.
+ /// </summary>
+ /// <returns>True if there are more records to read, otherwise false.</returns>
+ Task<bool> ReadAsync();
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/IReader.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/IReader.cs
new file mode 100644
index 0000000..3eb598e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/IReader.cs
@@ -0,0 +1,126 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Threading;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Defines methods used to read parsed data
+ /// from a CSV file.
+ /// </summary>
+ public interface IReader : IReaderRow, IDisposable
+ {
+ /// <summary>
+ /// Reads the header record without reading the first row.
+ /// </summary>
+ /// <returns>True if there are more records, otherwise false.</returns>
+ bool ReadHeader();
+
+ /// <summary>
+ /// Advances the reader to the next record. This will not read headers.
+ /// You need to call <see cref="Read"/> then <see cref="ReadHeader"/>
+ /// for the headers to be read.
+ /// </summary>
+ /// <returns>True if there are more records, otherwise false.</returns>
+ bool Read();
+
+ /// <summary>
+ /// Advances the reader to the next record. This will not read headers.
+ /// You need to call <see cref="ReadAsync"/> then <see cref="ReadHeader"/>
+ /// for the headers to be read.
+ /// </summary>
+ /// <returns>True if there are more records, otherwise false.</returns>
+ Task<bool> ReadAsync();
+
+ /// <summary>
+ /// Gets all the records in the CSV file and
+ /// converts each to <see cref="Type"/> T. The Read method
+ /// should not be used when using this.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the record.</typeparam>
+ /// <returns>An <see cref="IEnumerable{T}" /> of records.</returns>
+ IEnumerable<T> GetRecords<T>();
+
+ /// <summary>
+ /// Gets all the records in the CSV file and converts
+ /// each to <see cref="System.Type"/> T. The read method
+ /// should not be used when using this.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="System.Type"/> of the record.</typeparam>
+ /// <param name="anonymousTypeDefinition">The anonymous type definition to use for the records.</param>
+ /// <returns>An <see cref="IEnumerable{T}"/> of records.</returns>
+ IEnumerable<T> GetRecords<T>(T anonymousTypeDefinition);
+
+ /// <summary>
+ /// Gets all the records in the CSV file and
+ /// converts each to <see cref="Type"/> T. The Read method
+ /// should not be used when using this.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> of the record.</param>
+ /// <returns>An <see cref="IEnumerable{Object}" /> of records.</returns>
+ IEnumerable<object> GetRecords(Type type);
+
+ /// <summary>
+ /// Enumerates the records hydrating the given record instance with row data.
+ /// The record instance is re-used and not cleared on each enumeration.
+ /// This only works for streaming rows. If any methods are called on the projection
+ /// that force the evaluation of the IEnumerable, such as ToList(), the entire list
+ /// will contain the same instance of the record, which is the last row.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ /// <param name="record">The record to fill each enumeration.</param>
+ /// <returns>An <see cref="IEnumerable{T}"/> of records.</returns>
+ IEnumerable<T> EnumerateRecords<T>(T record);
+
+#if !NET45
+ /// <summary>
+ /// Gets all the records in the CSV file and
+ /// converts each to <see cref="Type"/> T. The Read method
+ /// should not be used when using this.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the record.</typeparam>
+ /// <param name="cancellationToken">The cancellation token to stop the writing.</param>
+ /// <returns>An <see cref="IAsyncEnumerable{T}" /> of records.</returns>
+ IAsyncEnumerable<T> GetRecordsAsync<T>(CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Gets all the records in the CSV file and converts
+ /// each to <see cref="System.Type"/> T. The read method
+ /// should not be used when using this.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="System.Type"/> of the record.</typeparam>
+ /// <param name="anonymousTypeDefinition">The anonymous type definition to use for the records.</param>
+ /// <param name="cancellationToken">The cancellation token to stop the writing.</param>
+ /// <returns>An <see cref="IAsyncEnumerable{T}"/> of records.</returns>
+ IAsyncEnumerable<T> GetRecordsAsync<T>(T anonymousTypeDefinition, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Gets all the records in the CSV file and
+ /// converts each to <see cref="Type"/> T. The Read method
+ /// should not be used when using this.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> of the record.</param>
+ /// <param name="cancellationToken">The cancellation token to stop the writing.</param>
+ /// <returns>An <see cref="IAsyncEnumerable{Object}" /> of records.</returns>
+ IAsyncEnumerable<object> GetRecordsAsync(Type type, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Enumerates the records hydrating the given record instance with row data.
+ /// The record instance is re-used and not cleared on each enumeration.
+ /// This only works for streaming rows. If any methods are called on the projection
+ /// that force the evaluation of the IEnumerable, such as ToList(), the entire list
+ /// will contain the same instance of the record, which is the last row.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ /// <param name="record">The record to fill each enumeration.</param>
+ /// /// <param name="cancellationToken">The cancellation token to stop the writing.</param>
+ /// <returns>An <see cref="IAsyncEnumerable{T}"/> of records.</returns>
+ IAsyncEnumerable<T> EnumerateRecordsAsync<T>(T record, CancellationToken cancellationToken = default(CancellationToken));
+#endif
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/IReaderRow.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/IReaderRow.cs
new file mode 100644
index 0000000..0d75a53
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/IReaderRow.cs
@@ -0,0 +1,428 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+using CsvHelper.TypeConversion;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Defines methods used to read parsed data
+ /// from a CSV file row.
+ /// </summary>
+ public interface IReaderRow
+ {
+ /// <summary>
+ /// Gets the column count of the current row.
+ /// This should match <see cref="IParser.Count"/>.
+ /// </summary>
+ int ColumnCount { get; }
+
+ /// <summary>
+ /// Gets the field index the reader is currently on.
+ /// </summary>
+ int CurrentIndex { get; }
+
+ /// <summary>
+ /// Gets the header record.
+ /// </summary>
+ string[]? HeaderRecord { get; }
+
+ /// <summary>
+ /// Gets the parser.
+ /// </summary>
+ IParser Parser { get; }
+
+ /// <summary>
+ /// Gets the reading context.
+ /// </summary>
+ CsvContext Context { get; }
+
+ /// <summary>
+ /// Gets or sets the configuration.
+ /// </summary>
+ IReaderConfiguration Configuration { get; }
+
+ /// <summary>
+ /// Gets the raw field at position (column) index.
+ /// </summary>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <returns>The raw field.</returns>
+ string? this[int index] { get; }
+
+ /// <summary>
+ /// Gets the raw field at position (column) name.
+ /// </summary>
+ /// <param name="name">The named index of the field.</param>
+ /// <returns>The raw field.</returns>
+ string? this[string name] { get; }
+
+ /// <summary>
+ /// Gets the raw field at position (column) name.
+ /// </summary>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <returns>The raw field.</returns>
+ string? this[string name, int index] { get; }
+
+ /// <summary>
+ /// Gets the raw field at position (column) index.
+ /// </summary>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <returns>The raw field.</returns>
+ string? GetField(int index);
+
+ /// <summary>
+ /// Gets the raw field at position (column) name.
+ /// </summary>
+ /// <param name="name">The named index of the field.</param>
+ /// <returns>The raw field.</returns>
+ string? GetField(string name);
+
+ /// <summary>
+ /// Gets the raw field at position (column) name and the index
+ /// instance of that field. The index is used when there are
+ /// multiple columns with the same header name.
+ /// </summary>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <returns>The raw field.</returns>
+ string? GetField(string name, int index);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Object"/> using
+ /// the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The type of the field.</param>
+ /// <param name="index">The index of the field.</param>
+ /// <returns>The field converted to <see cref="Object"/>.</returns>
+ object? GetField(Type type, int index);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Object"/> using
+ /// the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The type of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <returns>The field converted to <see cref="Object"/>.</returns>
+ object? GetField(Type type, string name);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Object"/> using
+ /// the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The type of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <returns>The field converted to <see cref="Object"/>.</returns>
+ object? GetField(Type type, string name, int index);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Object"/> using
+ /// the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The type of the field.</param>
+ /// <param name="index">The index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Object"/>.</param>
+ /// <returns>The field converted to <see cref="Object"/>.</returns>
+ object? GetField(Type type, int index, ITypeConverter converter);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Object"/> using
+ /// the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The type of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Object"/>.</param>
+ /// <returns>The field converted to <see cref="Object"/>.</returns>
+ object? GetField(Type type, string name, ITypeConverter converter);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Object"/> using
+ /// the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The type of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Object"/>.</param>
+ /// <returns>The field converted to <see cref="Object"/>.</returns>
+ object? GetField(Type type, string name, int index, ITypeConverter converter);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) index.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T>(int index);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T>(string name);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position
+ /// (column) name and the index instance of that field. The index
+ /// is used when there are multiple columns with the same header name.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <returns></returns>
+ T? GetField<T>(string name, int index);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) index using
+ /// the given <see cref="ITypeConverter" />.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T>(int index, ITypeConverter converter);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name using
+ /// the given <see cref="ITypeConverter" />.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T>(string name, ITypeConverter converter);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position
+ /// (column) name and the index instance of that field. The index
+ /// is used when there are multiple columns with the same header name.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T>(string name, int index, ITypeConverter converter);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) index using
+ /// the given <see cref="ITypeConverter" />.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <typeparam name="TConverter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</typeparam>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T, TConverter>(int index) where TConverter : ITypeConverter;
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name using
+ /// the given <see cref="ITypeConverter" />.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <typeparam name="TConverter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T, TConverter>(string name) where TConverter : ITypeConverter;
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position
+ /// (column) name and the index instance of that field. The index
+ /// is used when there are multiple columns with the same header name.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <typeparam name="TConverter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <returns>The field converted to <see cref="Type"/> T.</returns>
+ T? GetField<T, TConverter>(string name, int index) where TConverter : ITypeConverter;
+
+ /// <summary>
+ /// Gets the field converted to <see cref="System.Type"/> T at position (column) index.
+ /// </summary>
+ /// <param name="type">The <see cref="System.Type"/> of the field.</param>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <param name="field">The field converted to type T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField(Type type, int index, out object? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="System.Type"/> T at position (column) name.
+ /// </summary>
+ /// <param name="type">The <see cref="System.Type"/> of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="field">The field converted to <see cref="System.Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField(Type type, string name, out object? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="System.Type"/> T at position
+ /// (column) name and the index instance of that field. The index
+ /// is used when there are multiple columns with the same header name.
+ /// </summary>
+ /// <param name="type">The <see cref="System.Type"/> of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <param name="field">The field converted to <see cref="System.Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField(Type type, string name, int index, out object? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="System.Type"/> T at position (column) index
+ /// using the specified <see cref="ITypeConverter" />.
+ /// </summary>
+ /// <param name="type">The <see cref="System.Type"/> of the field.</param>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="System.Type"/> T.</param>
+ /// <param name="field">The field converted to <see cref="System.Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField(Type type, int index, ITypeConverter converter, out object? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="System.Type"/> T at position (column) name
+ /// using the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="System.Type"/> of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="System.Type"/> T.</param>
+ /// <param name="field">The field converted to <see cref="System.Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField(Type type, string name, ITypeConverter converter, out object? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="System.Type"/> T at position (column) name
+ /// using the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="System.Type"/> of the field.</param>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="System.Type"/> T.</param>
+ /// <param name="field">The field converted to <see cref="System.Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField(Type type, string name, int index, ITypeConverter converter, out object? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) index.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <param name="field">The field converted to type T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T>(int index, out T? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T>(string name, out T? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position
+ /// (column) name and the index instance of that field. The index
+ /// is used when there are multiple columns with the same header name.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T>(string name, int index, out T? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) index
+ /// using the specified <see cref="ITypeConverter" />.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T>(int index, ITypeConverter converter, out T? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name
+ /// using the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T>(string name, ITypeConverter converter, out T? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name
+ /// using the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <param name="converter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T>(string name, int index, ITypeConverter converter, out T? field);
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) index
+ /// using the specified <see cref="ITypeConverter" />.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <typeparam name="TConverter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</typeparam>
+ /// <param name="index">The zero based index of the field.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T, TConverter>(int index, out T? field) where TConverter : ITypeConverter;
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name
+ /// using the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <typeparam name="TConverter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T, TConverter>(string name, out T? field) where TConverter : ITypeConverter;
+
+ /// <summary>
+ /// Gets the field converted to <see cref="Type"/> T at position (column) name
+ /// using the specified <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the field.</typeparam>
+ /// <typeparam name="TConverter">The <see cref="ITypeConverter"/> used to convert the field to <see cref="Type"/> T.</typeparam>
+ /// <param name="name">The named index of the field.</param>
+ /// <param name="index">The zero based index of the instance of the field.</param>
+ /// <param name="field">The field converted to <see cref="Type"/> T.</param>
+ /// <returns>A value indicating if the get was successful.</returns>
+ bool TryGetField<T, TConverter>(string name, int index, out T? field) where TConverter : ITypeConverter;
+
+ /// <summary>
+ /// Gets the record converted into <see cref="Type"/> T.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="Type"/> of the record.</typeparam>
+ /// <returns>The record converted to <see cref="Type"/> T.</returns>
+ T? GetRecord<T>();
+
+ /// <summary>
+ /// Get the record converted into <see cref="System.Type"/> T.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="System.Type"/> of the record.</typeparam>
+ /// <param name="anonymousTypeDefinition">The anonymous type definition to use for the record.</param>
+ /// <returns>The record converted to <see cref="System.Type"/> T.</returns>
+ T? GetRecord<T>(T anonymousTypeDefinition);
+
+ /// <summary>
+ /// Gets the record.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> of the record.</param>
+ /// <returns>The record.</returns>
+ object? GetRecord(Type type);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/IWriter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/IWriter.cs
new file mode 100644
index 0000000..f181b0d
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/IWriter.cs
@@ -0,0 +1,86 @@
+// Copyright 2009-2022 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;
+using System.Collections;
+using System.IO;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Defines methods used to write to a CSV file.
+ /// </summary>
+ public interface IWriter : IWriterRow, IDisposable
+#if !NET45 && !NET47 && !NETSTANDARD2_0
+ , IAsyncDisposable
+#endif
+ {
+ /// <summary>
+ /// Flushes the internal buffer to the <see cref="TextWriter"/> then
+ /// flushes the <see cref="TextWriter"/>.
+ /// </summary>
+ void Flush();
+
+ /// <summary>
+ /// Flushes the internal buffer to the <see cref="TextWriter"/> then
+ /// flushes the <see cref="TextWriter"/>.
+ /// </summary>
+ Task FlushAsync();
+
+ /// <summary>
+ /// Ends writing of the current record and starts a new record.
+ /// This flushes the buffer to the <see cref="TextWriter"/> but
+ /// does not flush the <see cref="TextWriter"/>.
+ /// </summary>
+ void NextRecord();
+
+ /// <summary>
+ /// Ends writing of the current record and starts a new record.
+ /// This flushes the buffer to the <see cref="TextWriter"/> but
+ /// does not flush the <see cref="TextWriter"/>.
+ /// </summary>
+ Task NextRecordAsync();
+
+ /// <summary>
+ /// Writes the list of records to the CSV file.
+ /// </summary>
+ /// <param name="records">The records to write.</param>
+ void WriteRecords(IEnumerable records);
+
+ /// <summary>
+ /// Writes the list of records to the CSV file.
+ /// </summary>
+ /// <typeparam name="T">Record type.</typeparam>
+ /// <param name="records">The records to write.</param>
+ void WriteRecords<T>(IEnumerable<T> records);
+
+ /// <summary>
+ /// Writes the list of records to the CSV file.
+ /// </summary>
+ /// <param name="records">The records to write.</param>
+ /// <param name="cancellationToken">The cancellation token to stop the writing.</param>
+ Task WriteRecordsAsync(IEnumerable records, CancellationToken cancellationToken = default);
+
+ /// <summary>
+ /// Writes the list of records to the CSV file.
+ /// </summary>
+ /// <typeparam name="T">Record type.</typeparam>
+ /// <param name="records">The records to write.</param>
+ /// <param name="cancellationToken">The cancellation token to stop the writing.</param>
+ Task WriteRecordsAsync<T>(IEnumerable<T> records, CancellationToken cancellationToken = default);
+
+#if !NET45
+ /// <summary>
+ /// Writes the list of records to the CSV file.
+ /// </summary>
+ /// <typeparam name="T">Record type.</typeparam>
+ /// <param name="records">The records to write.</param>
+ /// <param name="cancellationToken">The cancellation token to stop the writing.</param>
+ Task WriteRecordsAsync<T>(IAsyncEnumerable<T> records, CancellationToken cancellationToken = default);
+#endif
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/IWriterRow.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/IWriterRow.cs
new file mode 100644
index 0000000..3b773b1
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/IWriterRow.cs
@@ -0,0 +1,135 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+using CsvHelper.TypeConversion;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Defines methods used to write a CSV row.
+ /// </summary>
+ public interface IWriterRow
+ {
+ /// <summary>
+ /// The header record.
+ /// </summary>
+ string[] HeaderRecord { get; }
+
+ /// <summary>
+ /// The current row.
+ /// </summary>
+ int Row { get; }
+
+ /// <summary>
+ /// The current field index.
+ /// </summary>
+ int Index { get; }
+
+ /// <summary>
+ /// Gets the writing context.
+ /// </summary>
+ CsvContext Context { get; }
+
+ /// <summary>
+ /// Gets or sets the configuration.
+ /// </summary>
+ IWriterConfiguration Configuration { get; }
+
+ /// <summary>
+ /// Writes a field that has already been converted to a
+ /// <see cref="string"/> from an <see cref="ITypeConverter"/>.
+ /// If the field is null, it won't get written. A type converter
+ /// will always return a string, even if field is null. If the
+ /// converter returns a null, it means that the converter has already
+ /// written data, and the returned value should not be written.
+ /// </summary>
+ /// <param name="field">The converted field to write.</param>
+ /// <param name="fieldType">The type of the field before it was converted into a string.</param>
+ void WriteConvertedField(string field, Type fieldType);
+
+ /// <summary>
+ /// Writes the field to the CSV file. The field
+ /// may get quotes added to it.
+ /// When all fields are written for a record,
+ /// <see cref="IWriter.NextRecord()" /> must be called
+ /// to complete writing of the current record.
+ /// </summary>
+ /// <param name="field">The field to write.</param>
+ void WriteField(string field);
+
+ /// <summary>
+ /// Writes the field to the CSV file. This will
+ /// ignore any need to quote and ignore
+ /// <see cref="CsvHelper.Configuration.CsvConfiguration.ShouldQuote"/>
+ /// and just quote based on the shouldQuote
+ /// parameter.
+ /// When all fields are written for a record,
+ /// <see cref="IWriter.NextRecord()" /> must be called
+ /// to complete writing of the current record.
+ /// </summary>
+ /// <param name="field">The field to write.</param>
+ /// <param name="shouldQuote">True to quote the field, otherwise false.</param>
+ void WriteField(string field, bool shouldQuote);
+
+ /// <summary>
+ /// Writes the field to the CSV file.
+ /// When all fields are written for a record,
+ /// <see cref="IWriter.NextRecord()" /> must be called
+ /// to complete writing of the current record.
+ /// </summary>
+ /// <typeparam name="T">The type of the field.</typeparam>
+ /// <param name="field">The field to write.</param>
+ void WriteField<T>(T field);
+
+ /// <summary>
+ /// Writes the field to the CSV file.
+ /// When all fields are written for a record,
+ /// <see cref="IWriter.NextRecord" /> must be called
+ /// to complete writing of the current record.
+ /// </summary>
+ /// <typeparam name="T">The type of the field.</typeparam>
+ /// <param name="field">The field to write.</param>
+ /// <param name="converter">The converter used to convert the field into a string.</param>
+ void WriteField<T>(T field, ITypeConverter converter);
+
+ /// <summary>
+ /// Writes the field to the CSV file
+ /// using the given <see cref="ITypeConverter"/>.
+ /// When all fields are written for a record,
+ /// <see cref="IWriter.NextRecord()" /> must be called
+ /// to complete writing of the current record.
+ /// </summary>
+ /// <typeparam name="T">The type of the field.</typeparam>
+ /// <typeparam name="TConverter">The type of the converter.</typeparam>
+ /// <param name="field">The field to write.</param>
+ void WriteField<T, TConverter>(T field);
+
+ /// <summary>
+ /// Writes a comment.
+ /// </summary>
+ /// <param name="comment">The comment to write.</param>
+ void WriteComment(string comment);
+
+ /// <summary>
+ /// Writes the header record from the given members.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ void WriteHeader<T>();
+
+ /// <summary>
+ /// Writes the header record from the given members.
+ /// </summary>
+ /// <param name="type">The type of the record.</param>
+ void WriteHeader(Type type);
+
+ /// <summary>
+ /// Writes the record to the CSV file.
+ /// </summary>
+ /// <typeparam name="T">The type of the record.</typeparam>
+ /// <param name="record">The record to write.</param>
+ void WriteRecord<T>(T record);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Icon.png b/ThirdParty/CsvHelper-master/src/CsvHelper/Icon.png
new file mode 100644
index 0000000..e8c5d82
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Icon.png
Binary files differ
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/InvalidHeader.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/InvalidHeader.cs
new file mode 100644
index 0000000..0383623
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/InvalidHeader.cs
@@ -0,0 +1,28 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Invalid header information.
+ /// </summary>
+ public class InvalidHeader
+ {
+ /// <summary>
+ /// Header names mapped to a CSV field that couldn't be found.
+ /// </summary>
+ public List<string> Names { get; set; } = new List<string>();
+
+ /// <summary>
+ /// Header name index maped to a CSV field that couldn't be found.
+ /// </summary>
+ public int Index { get; set; }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/LinkedListExtensions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/LinkedListExtensions.cs
new file mode 100644
index 0000000..ffe6fdd
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/LinkedListExtensions.cs
@@ -0,0 +1,29 @@
+// Copyright 2009-2022 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.Collections.Generic;
+
+namespace CsvHelper
+{
+ internal static class LinkedListExtensions
+ {
+ public static void Drop<T>(this LinkedList<T> list, LinkedListNode<T>? node)
+ {
+ if (list.Count == 0)
+ {
+ return;
+ }
+
+ while (list.Count > 0)
+ {
+ var nodeToRemove = list.Last;
+ list.RemoveLast();
+ if (nodeToRemove == node)
+ {
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/MaxFieldSizeException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/MaxFieldSizeException.cs
new file mode 100644
index 0000000..fd3bc21
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/MaxFieldSizeException.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2019 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 System;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents an error due to a field that is too large.
+ /// </summary>
+ [Serializable]
+ public class MaxFieldSizeException : CsvHelperException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MaxFieldSizeException"/> class.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ public MaxFieldSizeException(CsvContext context) : base(context) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MaxFieldSizeException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public MaxFieldSizeException(CsvContext context, string message) : base(context, message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MaxFieldSizeException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public MaxFieldSizeException(CsvContext context, string message, Exception innerException) : base(context, message, innerException) { }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/MissingFieldException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/MissingFieldException.cs
new file mode 100644
index 0000000..2b93dd4
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/MissingFieldException.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents an error caused because a field is missing
+ /// in the header while reading a CSV file.
+ /// </summary>
+ [Serializable]
+ public class MissingFieldException : ReaderException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MissingFieldException"/> class.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ public MissingFieldException(CsvContext context) : base(context) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MissingFieldException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public MissingFieldException(CsvContext context, string message) : base(context, message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MissingFieldException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public MissingFieldException(CsvContext context, string message, Exception innerException) : base(context, message, innerException) { }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ObjectCreator.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ObjectCreator.cs
new file mode 100644
index 0000000..4e1789e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ObjectCreator.cs
@@ -0,0 +1,218 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Efficiently creates instances of object types.
+ /// </summary>
+ public class ObjectCreator
+ {
+ private readonly Dictionary<int, Func<object[], object>> cache = new Dictionary<int, Func<object[], object>>();
+
+ /// <summary>
+ /// Creates an instance of type T using the given arguments.
+ /// </summary>
+ /// <typeparam name="T">The type to create an instance of.</typeparam>
+ /// <param name="args">The constrcutor arguments.</param>
+ public T CreateInstance<T>(params object[] args)
+ {
+ return (T)CreateInstance(typeof(T), args);
+ }
+
+ /// <summary>
+ /// Creates an instance of the given type using the given arguments.
+ /// </summary>
+ /// <param name="type">The type to create an instance of.</param>
+ /// <param name="args">The constructor arguments.</param>
+ public object CreateInstance(Type type, params object[] args)
+ {
+ var func = GetFunc(type, args);
+
+ return func(args);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private Func<object[], object> GetFunc(Type type, object[] args)
+ {
+ var argTypes = GetArgTypes(args);
+ var key = GetConstructorCacheKey(type, argTypes);
+ if (!cache.TryGetValue(key, out var func))
+ {
+ cache[key] = func = CreateInstanceFunc(type, argTypes);
+ }
+
+ return func;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static Type[] GetArgTypes(object[] args)
+ {
+ var argTypes = new Type[args.Length];
+ for (var i = 0; i < args.Length; i++)
+ {
+ argTypes[i] = args[i]?.GetType() ?? typeof(object);
+ }
+
+ return argTypes;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int GetConstructorCacheKey(Type type, Type[] args)
+ {
+#if !NET45
+ var hashCode = new HashCode();
+ hashCode.Add(type.GetHashCode());
+ for (var i = 0; i < args.Length; i++)
+ {
+ hashCode.Add(args[i].GetHashCode());
+ }
+
+ return hashCode.ToHashCode();
+#else
+ unchecked
+ {
+ var hash = 17;
+ hash = hash * 31 + type.GetHashCode();
+ for (var i = 0; i < args.Length; i++)
+ {
+ hash = hash * 31 + (args[i].GetHashCode());
+ }
+
+ return hash;
+ }
+#endif
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static Func<object[], object> CreateInstanceFunc(Type type, Type[] argTypes)
+ {
+ var parameterExpression = Expression.Parameter(typeof(object[]), "args");
+
+ Expression body;
+ if (type.IsValueType)
+ {
+ if (argTypes.Length > 0)
+ {
+ throw GetConstructorNotFoundException(type, argTypes);
+ }
+
+ body = Expression.Convert(Expression.Default(type), typeof(object));
+ }
+ else
+ {
+ var constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ var constructor = GetConstructor(constructors, type, argTypes);
+
+ var parameters = constructor.GetParameters();
+ var parameterTypes = new Type[parameters.Length];
+ for (var i = 0; i < parameters.Length; i++)
+ {
+ parameterTypes[i] = parameters[i].ParameterType;
+ }
+
+ var arguments = new List<Expression>();
+ for (var i = 0; i < parameterTypes.Length; i++)
+ {
+ var parameterType = parameterTypes[i];
+ var arrayIndexExpression = Expression.ArrayIndex(parameterExpression, Expression.Constant(i));
+ var convertExpression = Expression.Convert(arrayIndexExpression, parameterType);
+ arguments.Add(convertExpression);
+ }
+
+ body = Expression.New(constructor, arguments);
+ }
+
+ var lambda = Expression.Lambda<Func<object[], object>>(body, new[] { parameterExpression });
+ var func = lambda.Compile();
+
+ return func;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static ConstructorInfo GetConstructor(ConstructorInfo[] constructors, Type type, Type[] argTypes)
+ {
+ var matchType = MatchType.Exact;
+ var fuzzyMatches = new List<ConstructorInfo>();
+ for (var i = 0; i < constructors.Length; i++)
+ {
+ var constructor = constructors[i];
+ var parameters = constructors[i].GetParameters();
+
+ if (parameters.Length != argTypes.Length)
+ {
+ continue;
+ }
+
+ for (var j = 0; j < parameters.Length && j < argTypes.Length; j++)
+ {
+ var parameterType = parameters[j].ParameterType;
+ var argType = argTypes[j];
+
+ if (argType == parameterType)
+ {
+ matchType = MatchType.Exact;
+ continue;
+ }
+
+ if (!parameterType.IsValueType && (parameterType.IsAssignableFrom(argType) || argType == typeof(object)))
+ {
+ matchType = MatchType.Fuzzy;
+ continue;
+ }
+
+ matchType = MatchType.None;
+ break;
+ }
+
+ if (matchType == MatchType.Exact)
+ {
+ // Only possible to have one exact match.
+ return constructor;
+ }
+
+ if (matchType == MatchType.Fuzzy)
+ {
+ fuzzyMatches.Add(constructor);
+ }
+ }
+
+ if (fuzzyMatches.Count == 1)
+ {
+ return fuzzyMatches[0];
+ }
+
+ if (fuzzyMatches.Count > 1)
+ {
+ throw new AmbiguousMatchException();
+ }
+
+ throw GetConstructorNotFoundException(type, argTypes);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static MissingMethodException GetConstructorNotFoundException(Type type, Type[] argTypes)
+ {
+ var signature = $"{type.FullName}({string.Join(", ", argTypes.Select(a => a.FullName))})";
+
+ throw new MissingMethodException($"Constructor '{signature}' was not found.");
+ }
+
+ private enum MatchType
+ {
+ None = 0,
+ Exact = 1,
+ Fuzzy = 2
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ObjectResolver.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ObjectResolver.cs
new file mode 100644
index 0000000..99a17e0
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ObjectResolver.cs
@@ -0,0 +1,143 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Creates objects from a given type.
+ /// </summary>
+ public class ObjectResolver : IObjectResolver
+ {
+ private static IObjectResolver current;
+ private readonly ObjectCreator objectCreator = new ObjectCreator();
+
+ /// <summary>
+ /// Gets or sets the current resolver.
+ /// Use an instance of this instead if at all possible.
+ /// </summary>
+ public static IObjectResolver Current
+ {
+ get
+ {
+ return current;
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new InvalidOperationException($"{nameof(IObjectResolver)} cannot be null.");
+ }
+
+ current = value;
+ }
+ }
+
+ /// <summary>
+ /// A value indicating if the resolver's <see cref="CanResolve"/>
+ /// returns false that an object will still be created using
+ /// CsvHelper's object creation. True to fallback, otherwise false.
+ /// Default value is true.
+ /// </summary>
+ public bool UseFallback { get; private set; }
+
+ /// <summary>
+ /// A function that returns a value indicating if the resolver
+ /// is able to resolve the given type. True if the type can be
+ /// resolved, otherwise false.
+ /// </summary>
+ public Func<Type, bool> CanResolve { get; private set; }
+
+ /// <summary>
+ /// The function that creates an object from a given type.
+ /// </summary>
+ public Func<Type, object[], object> ResolveFunction { get; private set; }
+
+ static ObjectResolver()
+ {
+ var objectCreator = new ObjectCreator();
+ var locker = new object();
+ current = new ObjectResolver(type => true, (type, args) =>
+ {
+ lock (locker)
+ {
+ return objectCreator.CreateInstance(type, args);
+ }
+ });
+ }
+
+ /// <summary>
+ /// Creates an instance of the object resolver using default values.
+ /// </summary>
+ public ObjectResolver()
+ {
+ CanResolve = type => true;
+ ResolveFunction = ResolveWithObjectCreator;
+ UseFallback = true;
+ }
+
+ /// <summary>
+ /// Creates an instance of the object resolver using the given can create function
+ /// and create function.
+ /// </summary>
+ /// <param name="canResolve">A function that returns a value indicating if the resolver
+ /// is able to resolve the given type. True if the type can be
+ /// resolved, otherwise false.</param>
+ /// <param name="resolveFunction">The function that creates an object from a given type.</param>
+ /// <param name="useFallback">A value indicating if the resolver's <see cref="CanResolve"/>
+ /// returns false that an object will still be created using
+ /// CsvHelper's object creation. True to fallback, otherwise false.
+ /// Default value is true.</param>
+ public ObjectResolver(Func<Type, bool> canResolve, Func<Type, object[], object> resolveFunction, bool useFallback = true)
+ {
+ CanResolve = canResolve ?? throw new ArgumentNullException(nameof(canResolve));
+ ResolveFunction = resolveFunction ?? throw new ArgumentNullException(nameof(resolveFunction));
+ UseFallback = useFallback;
+ }
+
+ /// <summary>
+ /// Creates an object from the given type using the <see cref="ResolveFunction"/>
+ /// function. If <see cref="CanResolve"/> is false, the object will be
+ /// created using CsvHelper's default object creation. If <see cref="UseFallback"/>
+ /// is false, an exception is thrown.
+ /// </summary>
+ /// <param name="type">The type to create an instance from. The created object
+ /// may not be the same type as the given type.</param>
+ /// <param name="constructorArgs">Constructor arguments used to create the type.</param>
+ public object Resolve(Type type, params object[] constructorArgs)
+ {
+ if (CanResolve(type))
+ {
+ return ResolveFunction(type, constructorArgs);
+ }
+
+ if (UseFallback)
+ {
+ return objectCreator.CreateInstance(type, constructorArgs);
+ }
+
+ throw new CsvHelperException($"Type '{type.FullName}' can't be resolved and fallback is turned off.");
+ }
+
+ /// <summary>
+ /// Creates an object from the given type using the <see cref="ResolveFunction"/>
+ /// function. If <see cref="CanResolve"/> is false, the object will be
+ /// created using CsvHelper's default object creation. If <see cref="UseFallback"/>
+ /// is false, an exception is thrown.
+ /// </summary>
+ /// <typeparam name="T">The type to create an instance from. The created object
+ /// may not be the same type as the given type.</typeparam>
+ /// <param name="constructorArgs">Constructor arguments used to create the type.</param>
+ public T Resolve<T>(params object[] constructorArgs)
+ {
+ return (T)Resolve(typeof(T), constructorArgs);
+ }
+
+ private object ResolveWithObjectCreator(Type type, params object[] args)
+ {
+ return objectCreator.CreateInstance(type, args);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ParserException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ParserException.cs
new file mode 100644
index 0000000..a7c57e2
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ParserException.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents errors that occur while parsing a CSV file.
+ /// </summary>
+ [Serializable]
+ public class ParserException : CsvHelperException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ParserException"/> class.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ public ParserException(CsvContext context) : base(context) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ParserException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public ParserException(CsvContext context, string message) : base(context, message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ParserException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public ParserException(CsvContext context, string message, Exception innerException) : base(context, message, innerException) { }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/Properties/AssemblyInfo.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..95c1366
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/Properties/AssemblyInfo.cs
@@ -0,0 +1,13 @@
+// Copyright 2009-2022 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;
+using System.Runtime.CompilerServices;
+
+[assembly: CLSCompliant(true)]
+#if NCRUNCH
+[assembly: InternalsVisibleTo("CsvHelper.Tests")]
+#else
+[assembly: InternalsVisibleTo("CsvHelper.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001000db97564beef98ad18a76ba31f769fab92b14341c9c37ed12f8004bb2a1a7fe42ad829b0e285915a816f05a32325c5e0ba83bd69d8f4d26a0785ccf446749842ad038f7325601a99c59a323dfa7ecf210139159da0aad1822b5d9c9be6d914ecbaa8b8c908c4af798a89b8777010971d81975079a49662ced398c742ff186a94")]
+#endif
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ReaderException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ReaderException.cs
new file mode 100644
index 0000000..94e2421
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ReaderException.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents errors that occur while reading a CSV file.
+ /// </summary>
+ [Serializable]
+ public class ReaderException : CsvHelperException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ReaderException"/> class.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ public ReaderException(CsvContext context) : base(context) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ReaderException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public ReaderException(CsvContext context, string message) : base(context, message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ReaderException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public ReaderException(CsvContext context, string message, Exception innerException) : base(context, message, innerException) { }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionExtensions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionExtensions.cs
new file mode 100644
index 0000000..e67c0b8
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionExtensions.cs
@@ -0,0 +1,155 @@
+// Copyright 2009-2022 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;
+using System.Reflection;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+using System.Linq;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Extensions to help with reflection.
+ /// </summary>
+ public static class ReflectionExtensions
+ {
+ /// <summary>
+ /// Gets the type from the member.
+ /// </summary>
+ /// <param name="member">The member to get the type from.</param>
+ /// <returns>The type.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Type MemberType(this MemberInfo member)
+ {
+ var property = member as PropertyInfo;
+ if (property != null)
+ {
+ return property.PropertyType;
+ }
+
+ var field = member as FieldInfo;
+ if (field != null)
+ {
+ return field.FieldType;
+ }
+
+ throw new InvalidOperationException("Member is not a property or a field.");
+ }
+
+ /// <summary>
+ /// Gets a member expression for the member.
+ /// </summary>
+ /// <param name="member">The member to get the expression for.</param>
+ /// <param name="expression">The member expression.</param>
+ /// <returns>The member expression.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static MemberExpression GetMemberExpression(this MemberInfo member, Expression expression)
+ {
+ var property = member as PropertyInfo;
+ if (property != null)
+ {
+ return Expression.Property(expression, property);
+ }
+
+ var field = member as FieldInfo;
+ if (field != null)
+ {
+ return Expression.Field(expression, field);
+ }
+
+ throw new InvalidOperationException("Member is not a property or a field.");
+ }
+
+ /// <summary>
+ /// Gets a value indicating if the given type is anonymous.
+ /// True for anonymous, otherwise false.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsAnonymous(this Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ // https://stackoverflow.com/a/2483054/68499
+ var isAnonymous = Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
+ && type.IsGenericType
+ && type.Name.Contains("AnonymousType")
+ && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
+ && (type.Attributes & TypeAttributes.Public) != TypeAttributes.Public;
+
+ return isAnonymous;
+ }
+
+ /// <summary>
+ /// Gets a value indicating if the given type has a parameterless constructor.
+ /// True if it has a parameterless constructor, otherwise false.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool HasParameterlessConstructor(this Type type)
+ {
+ return type.GetConstructor(new Type[0]) != null;
+ }
+
+ /// <summary>
+ /// Gets a value indicating if the given type has any constructors.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool HasConstructor(this Type type)
+ {
+ return type.GetConstructors().Length > 0;
+ }
+
+ /// <summary>
+ /// Gets the constructor that contains the most parameters.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ConstructorInfo GetConstructorWithMostParameters(this Type type)
+ {
+ return type.GetConstructors()
+ .OrderByDescending(c => c.GetParameters().Length)
+ .First();
+ }
+
+ /// <summary>
+ /// Gets a value indicating if the type is a user defined struct.
+ /// True if it is a user defined struct, otherwise false.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsUserDefinedStruct(this Type type)
+ {
+ return type.IsValueType && !type.IsPrimitive && !type.IsEnum;
+ }
+
+ /// <summary>
+ /// Gets a string representation of the constructor.
+ /// </summary>
+ /// <param name="constructor">The constructor.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static string GetDefinition(this ConstructorInfo constructor)
+ {
+ var parameters = constructor.GetParameters();
+ var definition = $"{constructor.Name}({string.Join(", ", parameters.Select(p => p.GetDefinition()))})";
+
+ return definition;
+ }
+
+ /// <summary>
+ /// Gets a string representation of the parameter.
+ /// </summary>
+ /// <param name="parameter">The parameter.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static string GetDefinition(this ParameterInfo parameter)
+ {
+ return $"{parameter.ParameterType.Name} {parameter.Name}";
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs
new file mode 100644
index 0000000..b026186
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs
@@ -0,0 +1,204 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using CsvHelper.Configuration;
+using CsvHelper.Configuration.Attributes;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Common reflection tasks.
+ /// </summary>
+ internal static class ReflectionHelper
+ {
+ /// <summary>
+ /// Gets the <see cref="PropertyInfo"/> from the type where the property was declared.
+ /// </summary>
+ /// <param name="type">The type the property belongs to.</param>
+ /// <param name="property">The property to search.</param>
+ /// <param name="flags">Flags for how the property is retrieved.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static PropertyInfo GetDeclaringProperty(Type type, PropertyInfo property, BindingFlags flags)
+ {
+ if (property.DeclaringType != type)
+ {
+ var declaringProperty = property.DeclaringType.GetProperty(property.Name, flags);
+ return GetDeclaringProperty(property.DeclaringType, declaringProperty, flags);
+ }
+
+ return property;
+ }
+
+ /// <summary>
+ /// Gets the <see cref="FieldInfo"/> from the type where the field was declared.
+ /// </summary>
+ /// <param name="type">The type the field belongs to.</param>
+ /// <param name="field">The field to search.</param>
+ /// <param name="flags">Flags for how the field is retrieved.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static FieldInfo GetDeclaringField(Type type, FieldInfo field, BindingFlags flags)
+ {
+ if (field.DeclaringType != type)
+ {
+ var declaringField = field.DeclaringType.GetField(field.Name, flags);
+ return GetDeclaringField(field.DeclaringType, declaringField, flags);
+ }
+
+ return field;
+ }
+
+ /// <summary>
+ /// Walk up the inheritance tree collecting properties. This will get a unique set of properties in the
+ /// case where parents have the same property names as children.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> to get properties for.</param>
+ /// <param name="flags">The flags for getting the properties.</param>
+ /// <param name="overwrite">If true, parent class properties that are hidden by `new` child properties will be overwritten.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static List<PropertyInfo> GetUniqueProperties(Type type, BindingFlags flags, bool overwrite = false)
+ {
+ var ignoreBase = type.GetCustomAttribute(typeof(IgnoreBaseAttribute)) != null;
+
+ var properties = new Dictionary<string, PropertyInfo>();
+
+ flags |= BindingFlags.DeclaredOnly;
+ var currentType = type;
+ while (currentType != null)
+ {
+ var currentProperties = currentType.GetProperties(flags);
+ foreach (var property in currentProperties)
+ {
+ if (!properties.ContainsKey(property.Name) || overwrite)
+ {
+ properties[property.Name] = property;
+ }
+ }
+
+ if (ignoreBase)
+ {
+ break;
+ }
+
+ currentType = currentType.BaseType;
+ }
+
+ return properties.Values.ToList();
+ }
+
+ /// <summary>
+ /// Walk up the inheritance tree collecting fields. This will get a unique set of fields in the
+ /// case where parents have the same field names as children.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> to get fields for.</param>
+ /// <param name="flags">The flags for getting the fields.</param>
+ /// <param name="overwrite">If true, parent class fields that are hidden by `new` child fields will be overwritten.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static List<FieldInfo> GetUniqueFields(Type type, BindingFlags flags, bool overwrite = false)
+ {
+ var ignoreBase = type.GetCustomAttribute(typeof(IgnoreBaseAttribute)) != null;
+
+ var fields = new Dictionary<string, FieldInfo>();
+
+ flags |= BindingFlags.DeclaredOnly;
+ var currentType = type;
+ while (currentType != null)
+ {
+ var currentFields = currentType.GetFields(flags);
+ foreach (var field in currentFields)
+ {
+ if (!fields.ContainsKey(field.Name) || overwrite)
+ {
+ fields[field.Name] = field;
+ }
+ }
+
+ if (ignoreBase)
+ {
+ break;
+ }
+
+ currentType = currentType.BaseType;
+ }
+
+ return fields.Values.ToList();
+ }
+
+ /// <summary>
+ /// Gets the property from the expression.
+ /// </summary>
+ /// <typeparam name="TModel">The type of the model.</typeparam>
+ /// <typeparam name="TProperty">The type of the property.</typeparam>
+ /// <param name="expression">The expression.</param>
+ /// <returns>The <see cref="PropertyInfo"/> for the expression.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static MemberInfo GetMember<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
+ {
+ var member = GetMemberExpression(expression.Body).Member;
+ var property = member as PropertyInfo;
+ if (property != null)
+ {
+ return property;
+ }
+
+ var field = member as FieldInfo;
+ if (field != null)
+ {
+ return field;
+ }
+
+ throw new ConfigurationException($"'{member.Name}' is not a member.");
+ }
+
+ /// <summary>
+ /// Gets the member inheritance chain as a stack.
+ /// </summary>
+ /// <typeparam name="TModel">The type of the model.</typeparam>
+ /// <typeparam name="TProperty">The type of the property.</typeparam>
+ /// <param name="expression">The member expression.</param>
+ /// <returns>The inheritance chain for the given member expression as a stack.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Stack<MemberInfo> GetMembers<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
+ {
+ var stack = new Stack<MemberInfo>();
+
+ var currentExpression = expression.Body;
+ while (true)
+ {
+ var memberExpression = GetMemberExpression(currentExpression);
+ if (memberExpression == null)
+ {
+ break;
+ }
+
+ stack.Push(memberExpression.Member);
+ currentExpression = memberExpression.Expression;
+ }
+
+ return stack;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static MemberExpression? GetMemberExpression(Expression expression)
+ {
+ MemberExpression? memberExpression = null;
+ if (expression.NodeType == ExpressionType.Convert)
+ {
+ var body = (UnaryExpression)expression;
+ memberExpression = body.Operand as MemberExpression;
+ }
+ else if (expression.NodeType == ExpressionType.MemberAccess)
+ {
+ memberExpression = expression as MemberExpression;
+ }
+
+ return memberExpression;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ArrayConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ArrayConverter.cs
new file mode 100644
index 0000000..fb30ae1
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ArrayConverter.cs
@@ -0,0 +1,73 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="Array"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class ArrayConverter : IEnumerableConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ Array array;
+ var type = memberMapData.Member.MemberType().GetElementType();
+ var converter = row.Context.TypeConverterCache.GetConverter(type);
+
+ if (memberMapData.IsNameSet || row.Configuration.HasHeaderRecord && !memberMapData.IsIndexSet)
+ {
+ // Use the name.
+ var list = new List<object>();
+ var nameIndex = 0;
+ while (true)
+ {
+ if (!row.TryGetField(type, memberMapData.Names.FirstOrDefault(), nameIndex, out var field))
+ {
+ break;
+ }
+
+ list.Add(field);
+ nameIndex++;
+ }
+
+ array = (Array)ObjectResolver.Current.Resolve(memberMapData.Member.MemberType(), list.Count);
+ for (var i = 0; i < list.Count; i++)
+ {
+ array.SetValue(list[i], i);
+ }
+ }
+ else
+ {
+ // Use the index.
+ var indexEnd = memberMapData.IndexEnd < memberMapData.Index
+ ? row.Parser.Count - 1
+ : memberMapData.IndexEnd;
+
+ var arraySize = indexEnd - memberMapData.Index + 1;
+ array = (Array)ObjectResolver.Current.Resolve(memberMapData.Member.MemberType(), arraySize);
+ var arrayIndex = 0;
+ for (var i = memberMapData.Index; i <= indexEnd; i++)
+ {
+ var field = converter.ConvertFromString(row.GetField(i), row, memberMapData);
+ array.SetValue(field, arrayIndex);
+ arrayIndex++;
+ }
+ }
+
+ return array;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BigIntegerConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BigIntegerConverter.cs
new file mode 100644
index 0000000..efc06c9
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BigIntegerConverter.cs
@@ -0,0 +1,57 @@
+// Copyright 2009-2022 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;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="BigInteger"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class BigIntegerConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ if (value is BigInteger bi && memberMapData.TypeConverterOptions.Formats?.FirstOrDefault() == null)
+ {
+ return bi.ToString("R", memberMapData.TypeConverterOptions.CultureInfo);
+ }
+
+ return base.ConvertToString(value, row, memberMapData);
+ }
+
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (BigInteger.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var bi))
+ {
+ return bi;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BooleanConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BooleanConverter.cs
new file mode 100644
index 0000000..6ab2a9c
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BooleanConverter.cs
@@ -0,0 +1,72 @@
+// Copyright 2009-2022 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;
+using System.Linq;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="bool"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class BooleanConverter : DefaultTypeConverter
+ {
+ /// <inheritdoc/>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (bool.TryParse(text, out var b))
+ {
+ return b;
+ }
+
+ if (short.TryParse(text, out var sh))
+ {
+ if (sh == 0)
+ {
+ return false;
+ }
+ if (sh == 1)
+ {
+ return true;
+ }
+ }
+
+ var t = (text ?? string.Empty).Trim();
+ foreach (var trueValue in memberMapData.TypeConverterOptions.BooleanTrueValues)
+ {
+ if (memberMapData.TypeConverterOptions.CultureInfo.CompareInfo.Compare(trueValue, t, CompareOptions.IgnoreCase) == 0)
+ {
+ return true;
+ }
+ }
+
+ foreach (var falseValue in memberMapData.TypeConverterOptions.BooleanFalseValues)
+ {
+ if (memberMapData.TypeConverterOptions.CultureInfo.CompareInfo.Compare(falseValue, t, CompareOptions.IgnoreCase) == 0)
+ {
+ return false;
+ }
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+
+ /// <inheritdoc/>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ var b = value as bool?;
+ if (b == true && memberMapData.TypeConverterOptions.BooleanTrueValues.Count > 0)
+ {
+ return memberMapData.TypeConverterOptions.BooleanTrueValues.First();
+ }
+ else if (b == false && memberMapData.TypeConverterOptions.BooleanFalseValues.Count > 0)
+ {
+ return memberMapData.TypeConverterOptions.BooleanFalseValues.First();
+ }
+
+ return base.ConvertToString(value, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverter.cs
new file mode 100644
index 0000000..1f6c382
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverter.cs
@@ -0,0 +1,126 @@
+// Copyright 2009-2022 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;
+using System.Text;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="T:Byte[]"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class ByteArrayConverter : DefaultTypeConverter
+ {
+ private readonly ByteArrayConverterOptions options;
+ private readonly string HexStringPrefix;
+ private readonly byte ByteLength;
+
+ /// <summary>
+ /// Creates a new ByteArrayConverter using the given <see cref="ByteArrayConverterOptions"/>.
+ /// </summary>
+ /// <param name="options">The options.</param>
+ public ByteArrayConverter(ByteArrayConverterOptions options = ByteArrayConverterOptions.Hexadecimal | ByteArrayConverterOptions.HexInclude0x)
+ {
+ // Defaults to the literal format used by C# for whole numbers, and SQL Server for binary data.
+ this.options = options;
+ ValidateOptions();
+
+ HexStringPrefix = (options & ByteArrayConverterOptions.HexDashes) == ByteArrayConverterOptions.HexDashes ? "-" : string.Empty;
+ ByteLength = (options & ByteArrayConverterOptions.HexDashes) == ByteArrayConverterOptions.HexDashes ? (byte)3 : (byte)2;
+ }
+
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ if (value is byte[] byteArray)
+ {
+ return (options & ByteArrayConverterOptions.Base64) == ByteArrayConverterOptions.Base64
+ ? Convert.ToBase64String(byteArray)
+ : ByteArrayToHexString(byteArray);
+ }
+
+ return base.ConvertToString(value, row, memberMapData);
+ }
+
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text != null)
+ {
+ return (options & ByteArrayConverterOptions.Base64) == ByteArrayConverterOptions.Base64
+ ? Convert.FromBase64String(text)
+ : HexStringToByteArray(text);
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+
+ private string ByteArrayToHexString(byte[] byteArray)
+ {
+ var hexString = new StringBuilder();
+
+ if ((options & ByteArrayConverterOptions.HexInclude0x) == ByteArrayConverterOptions.HexInclude0x)
+ {
+ hexString.Append("0x");
+ }
+
+ if (byteArray.Length >= 1)
+ {
+ hexString.Append(byteArray[0].ToString("X2"));
+ }
+
+ for (var i = 1; i < byteArray.Length; i++)
+ {
+ hexString.Append(HexStringPrefix + byteArray[i].ToString("X2"));
+ }
+
+ return hexString.ToString();
+ }
+
+ private byte[] HexStringToByteArray(string hex)
+ {
+ var has0x = hex.StartsWith("0x");
+
+ var length = has0x
+ ? (hex.Length - 1) / ByteLength
+ : hex.Length + 1 / ByteLength;
+ var byteArray = new byte[length];
+ var has0xOffset = has0x ? 1 : 0;
+
+ for (var stringIndex = has0xOffset * 2; stringIndex < hex.Length; stringIndex += ByteLength)
+ {
+ byteArray[(stringIndex - has0xOffset) / ByteLength] = Convert.ToByte(hex.Substring(stringIndex, 2), 16);
+ }
+
+ return byteArray;
+ }
+
+ private void ValidateOptions()
+ {
+ if ((options & ByteArrayConverterOptions.Base64) == ByteArrayConverterOptions.Base64)
+ {
+ if ((options & (ByteArrayConverterOptions.HexInclude0x | ByteArrayConverterOptions.HexDashes | ByteArrayConverterOptions.Hexadecimal)) != ByteArrayConverterOptions.None)
+ {
+ throw new ConfigurationException($"{nameof(ByteArrayConverter)} must be configured exclusively with HexDecimal options, or exclusively with Base64 options. Was {options.ToString()}")
+ {
+ Data = { { "options", options } }
+ };
+ }
+ }
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverterOptions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverterOptions.cs
new file mode 100644
index 0000000..2ce9d7c
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverterOptions.cs
@@ -0,0 +1,44 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Options for converting byte arrays.
+ /// </summary>
+ [Flags]
+ public enum ByteArrayConverterOptions
+ {
+ /// <summary>
+ /// No options.
+ /// </summary>
+ None = 0,
+
+ // TypeOptions
+
+ /// <summary>
+ /// Hexadecimal encoding.
+ /// </summary>
+ Hexadecimal = 1,
+
+ /// <summary>
+ /// Base64 encoding.
+ /// </summary>
+ Base64 = 2,
+
+ // HexFormattingOptions
+
+ /// <summary>
+ /// Use dashes in between hex values.
+ /// </summary>
+ HexDashes = 4,
+
+ /// <summary>
+ /// Prefix hex number with 0x.
+ /// </summary>
+ HexInclude0x = 8,
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteConverter.cs
new file mode 100644
index 0000000..7583bd7
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteConverter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="byte"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class ByteConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (byte.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var b))
+ {
+ return b;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CharConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CharConverter.cs
new file mode 100644
index 0000000..fa3d487
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CharConverter.cs
@@ -0,0 +1,36 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="char"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class CharConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text != null && text.Length > 1)
+ {
+ text = text.Trim();
+ }
+
+ if (char.TryParse(text, out var c))
+ {
+ return c;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionConverterFactory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionConverterFactory.cs
new file mode 100644
index 0000000..0fb8c90
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionConverterFactory.cs
@@ -0,0 +1,175 @@
+// Copyright 2009-2022 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;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <inheritdoc />
+ public class CollectionConverterFactory : ITypeConverterFactory
+ {
+ private int dictionaryTypeHashCode = typeof(IDictionary).GetHashCode();
+ private List<int> enumerableTypeHashCodes = new List<int>
+ {
+ typeof(IList).GetHashCode(),
+ typeof(ICollection).GetHashCode(),
+ typeof(IEnumerable).GetHashCode(),
+ };
+
+ /// <inheritdoc />
+ public bool CanCreate(Type type)
+ {
+ switch (type)
+ {
+ case IList:
+ case IDictionary:
+ case ICollection:
+ case IEnumerable:
+ return true;
+ }
+
+ if (type.IsArray)
+ {
+ // ArrayConverter
+ return true;
+ }
+
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
+ {
+ // IDictionaryGenericConverter
+ return true;
+ }
+
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+ {
+ // IDictionaryGenericConverter
+ return true;
+ }
+
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
+ {
+ // CollectionGenericConverter
+ return true;
+ }
+
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Collection<>))
+ {
+ // CollectionGenericConverter
+ return true;
+ }
+
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IList<>))
+ {
+ // IEnumerableGenericConverter
+ return true;
+ }
+
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(ICollection<>))
+ {
+ // IEnumerableGenericConverter
+ return true;
+ }
+
+ if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ {
+ // IEnumerableGenericConverter
+ return true;
+ }
+
+ // A specific IEnumerable converter doesn't exist.
+ if (typeof(IEnumerable).IsAssignableFrom(type))
+ {
+ // EnumerableConverter
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <inheritdoc />
+ public bool Create(Type type, TypeConverterCache cache, out ITypeConverter typeConverter)
+ {
+ var typeHashCode = type.GetHashCode();
+
+ if (typeHashCode == dictionaryTypeHashCode)
+ {
+ typeConverter = new IDictionaryConverter();
+ return true;
+ }
+
+ if (enumerableTypeHashCodes.Contains(typeHashCode))
+ {
+ typeConverter = new IEnumerableConverter();
+ return true;
+ }
+
+ if (type.IsArray)
+ {
+ typeConverter = new ArrayConverter();
+ return true;
+ }
+
+ var isGenericType = type.GetTypeInfo().IsGenericType;
+ var genericTypeDefinition = type.GetGenericTypeDefinition();
+
+ if (isGenericType && genericTypeDefinition == typeof(Dictionary<,>))
+ {
+ typeConverter = new IDictionaryGenericConverter();
+ return true;
+ }
+
+ if (isGenericType && genericTypeDefinition == typeof(IDictionary<,>))
+ {
+ typeConverter = new IDictionaryGenericConverter();
+ return true;
+ }
+
+ if (isGenericType && genericTypeDefinition == typeof(List<>))
+ {
+ typeConverter = new CollectionGenericConverter();
+ return true;
+ }
+
+ if (isGenericType && genericTypeDefinition == typeof(Collection<>))
+ {
+ typeConverter = new CollectionGenericConverter();
+ return true;
+ }
+
+ if (isGenericType && genericTypeDefinition == typeof(IList<>))
+ {
+ typeConverter = new IEnumerableGenericConverter();
+ return true;
+ }
+
+ if (isGenericType && genericTypeDefinition == typeof(ICollection<>))
+ {
+ typeConverter = new IEnumerableGenericConverter();
+ return true;
+ }
+
+ if (isGenericType && genericTypeDefinition == typeof(IEnumerable<>))
+ {
+ typeConverter = new IEnumerableGenericConverter();
+ return true;
+ }
+
+ // A specific IEnumerable converter doesn't exist.
+ if (typeof(IEnumerable).IsAssignableFrom(type))
+ {
+ typeConverter = new EnumerableConverter();
+ return true;
+ }
+
+ throw new InvalidOperationException($"Cannot create collection converter for type '{type.FullName}'.");
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionGenericConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionGenericConverter.cs
new file mode 100644
index 0000000..9026f6a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionGenericConverter.cs
@@ -0,0 +1,64 @@
+// Copyright 2009-2022 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.Collections;
+using System.Collections.ObjectModel;
+using System.Linq;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="Collection{T}"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class CollectionGenericConverter : IEnumerableConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ // Since we're using the MemberType here, this converter can be used for multiple types
+ // as long as they implement IList.
+ var list = (IList)ObjectResolver.Current.Resolve(memberMapData.Member.MemberType());
+ var type = memberMapData.Member.MemberType().GetGenericArguments()[0];
+ var converter = row.Context.TypeConverterCache.GetConverter(type);
+
+ if (memberMapData.IsNameSet || row.Configuration.HasHeaderRecord && !memberMapData.IsIndexSet)
+ {
+ // Use the name.
+ var nameIndex = 0;
+ while (true)
+ {
+ if (!row.TryGetField(type, memberMapData.Names.FirstOrDefault(), nameIndex, out var field))
+ {
+ break;
+ }
+
+ list.Add(field);
+ nameIndex++;
+ }
+ }
+ else
+ {
+ // Use the index.
+ var indexEnd = memberMapData.IndexEnd < memberMapData.Index
+ ? row.Parser.Count - 1
+ : memberMapData.IndexEnd;
+
+ for (var i = memberMapData.Index; i <= indexEnd; i++)
+ {
+ var field = converter.ConvertFromString(row.GetField(i), row, memberMapData);
+ list.Add(field);
+ }
+ }
+
+ return list;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateOnlyConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateOnlyConverter.cs
new file mode 100644
index 0000000..faedb82
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateOnlyConverter.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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
+#if NET6_0
+using CsvHelper.Configuration;
+using System;
+using System.Globalization;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="DateOnly"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class DateOnlyConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text == null)
+ {
+ return base.ConvertFromString(null, row, memberMapData);
+ }
+
+ var formatProvider = (IFormatProvider)memberMapData.TypeConverterOptions.CultureInfo.GetFormat(typeof(DateTimeFormatInfo)) ?? memberMapData.TypeConverterOptions.CultureInfo;
+ var dateTimeStyle = memberMapData.TypeConverterOptions.DateTimeStyle ?? DateTimeStyles.None;
+
+ return memberMapData.TypeConverterOptions.Formats == null || memberMapData.TypeConverterOptions.Formats.Length == 0
+ ? DateOnly.Parse(text, formatProvider, dateTimeStyle)
+ : DateOnly.ParseExact(text, memberMapData.TypeConverterOptions.Formats, formatProvider, dateTimeStyle);
+ }
+ }
+}
+#endif
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeConverter.cs
new file mode 100644
index 0000000..b67f133
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeConverter.cs
@@ -0,0 +1,43 @@
+// Copyright 2009-2022 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;
+using System;
+using System.Globalization;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="DateTime"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class DateTimeConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text == null)
+ {
+ return base.ConvertFromString(null, row, memberMapData);
+ }
+
+ var formatProvider = (IFormatProvider)memberMapData.TypeConverterOptions.CultureInfo.GetFormat(typeof(DateTimeFormatInfo)) ?? memberMapData.TypeConverterOptions.CultureInfo;
+ var dateTimeStyle = memberMapData.TypeConverterOptions.DateTimeStyle ?? DateTimeStyles.None;
+
+ DateTime dateTime;
+ var success = memberMapData.TypeConverterOptions.Formats == null || memberMapData.TypeConverterOptions.Formats.Length == 0
+ ? DateTime.TryParse(text, formatProvider, dateTimeStyle, out dateTime)
+ : DateTime.TryParseExact(text, memberMapData.TypeConverterOptions.Formats, formatProvider, dateTimeStyle, out dateTime);
+
+ return success
+ ? dateTime
+ : base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeOffsetConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeOffsetConverter.cs
new file mode 100644
index 0000000..88ad90e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeOffsetConverter.cs
@@ -0,0 +1,43 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="DateTimeOffset"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class DateTimeOffsetConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text == null)
+ {
+ return base.ConvertFromString(null, row, memberMapData);
+ }
+
+ var formatProvider = (IFormatProvider)memberMapData.TypeConverterOptions.CultureInfo.GetFormat(typeof(DateTimeFormatInfo)) ?? memberMapData.TypeConverterOptions.CultureInfo;
+ var dateTimeStyle = memberMapData.TypeConverterOptions.DateTimeStyle ?? DateTimeStyles.None;
+
+ DateTimeOffset dateTimeOffset;
+ var success = memberMapData.TypeConverterOptions.Formats == null || memberMapData.TypeConverterOptions.Formats.Length == 0
+ ? DateTimeOffset.TryParse(text, formatProvider, dateTimeStyle, out dateTimeOffset)
+ : DateTimeOffset.TryParseExact(text, memberMapData.TypeConverterOptions.Formats, formatProvider, dateTimeStyle, out dateTimeOffset);
+
+ return success
+ ? dateTimeOffset
+ : base.ConvertFromString(null, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DecimalConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DecimalConverter.cs
new file mode 100644
index 0000000..855167e
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DecimalConverter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="decimal"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class DecimalConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Number;
+
+ if (decimal.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var d))
+ {
+ return d;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DefaultTypeConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DefaultTypeConverter.cs
new file mode 100644
index 0000000..57bf11d
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DefaultTypeConverter.cs
@@ -0,0 +1,62 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+using System.Linq;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="object"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class DefaultTypeConverter : ITypeConverter
+ {
+ /// <inheritdoc/>
+ public virtual object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (memberMapData.UseDefaultOnConversionFailure && memberMapData.IsDefaultSet && memberMapData.Member.MemberType() == memberMapData.Default?.GetType())
+ {
+ return memberMapData.Default;
+ }
+
+ if (!row.Configuration.ExceptionMessagesContainRawData)
+ {
+ text = $"Hidden because {nameof(IParserConfiguration.ExceptionMessagesContainRawData)} is false.";
+ }
+
+ text ??= string.Empty;
+
+ var message =
+ $"The conversion cannot be performed.{Environment.NewLine}" +
+ $" Text: '{text}'{Environment.NewLine}" +
+ $" MemberName: {memberMapData.Member?.Name}{Environment.NewLine}" +
+ $" MemberType: {memberMapData.Member?.MemberType().FullName}{Environment.NewLine}" +
+ $" TypeConverter: '{memberMapData.TypeConverter?.GetType().FullName}'";
+ throw new TypeConverterException(this, memberMapData, text, row.Context, message);
+ }
+
+ /// <inheritdoc/>
+ public virtual string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ if (value == null)
+ {
+ if (memberMapData.TypeConverterOptions.NullValues.Count > 0)
+ {
+ return memberMapData.TypeConverterOptions.NullValues.First();
+ }
+
+ return string.Empty;
+ }
+
+ if (value is IFormattable formattable)
+ {
+ var format = memberMapData.TypeConverterOptions.Formats?.FirstOrDefault();
+ return formattable.ToString(format, memberMapData.TypeConverterOptions.CultureInfo);
+ }
+
+ return value?.ToString() ?? string.Empty;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DoubleConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DoubleConverter.cs
new file mode 100644
index 0000000..b330831
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DoubleConverter.cs
@@ -0,0 +1,57 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+using System.Linq;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="double"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class DoubleConverter : DefaultTypeConverter
+ {
+ private Lazy<string> defaultFormat = new Lazy<string>(() => double.TryParse(double.MaxValue.ToString("R"), out var _) ? "R" : "G17");
+
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ var format = memberMapData.TypeConverterOptions.Formats?.FirstOrDefault() ?? defaultFormat.Value;
+
+ if (value is double d)
+ {
+ return d.ToString(format, memberMapData.TypeConverterOptions.CultureInfo);
+ }
+
+ return base.ConvertToString(value, row, memberMapData);
+ }
+
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Float | NumberStyles.AllowThousands;
+
+ if (double.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var d))
+ {
+ return d;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverter.cs
new file mode 100644
index 0000000..023a4f3
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverter.cs
@@ -0,0 +1,121 @@
+// Copyright 2009-2022 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;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using CsvHelper.Configuration;
+using CsvHelper.Configuration.Attributes;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="Enum"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class EnumConverter : DefaultTypeConverter
+ {
+ private readonly Type type;
+ private readonly Dictionary<string, string> enumNamesByAttributeNames = new Dictionary<string, string>();
+ private readonly Dictionary<string, string> enumNamesByAttributeNamesIgnoreCase = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ private readonly Dictionary<object, string> attributeNamesByEnumValues = new Dictionary<object, string>();
+
+ // enumNamesByAttributeNames
+ // enumNamesByAttributeNamesIgnoreCase
+ // [Name("Foo")]:One
+
+ // attributeNamesByEnumValues
+ // 1:[Name("Foo")]
+
+ /// <summary>
+ /// Creates a new <see cref="EnumConverter"/> for the given <see cref="Enum"/> <see cref="System.Type"/>.
+ /// </summary>
+ /// <param name="type">The type of the Enum.</param>
+ public EnumConverter(Type type)
+ {
+ if (!typeof(Enum).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
+ {
+ throw new ArgumentException($"'{type.FullName}' is not an Enum.");
+ }
+
+ this.type = type;
+
+ foreach (var value in Enum.GetValues(type))
+ {
+ var enumName = Enum.GetName(type, value) ?? string.Empty;
+
+ var nameAttribute = type.GetField(enumName)?.GetCustomAttribute<NameAttribute>();
+ if (nameAttribute != null && nameAttribute.Names.Length > 0)
+ {
+ foreach (var attributeName in nameAttribute.Names)
+ {
+ if (!enumNamesByAttributeNames.ContainsKey(attributeName))
+ {
+ enumNamesByAttributeNames.Add(attributeName, enumName);
+ }
+
+ if (!enumNamesByAttributeNamesIgnoreCase.ContainsKey(attributeName))
+ {
+ enumNamesByAttributeNamesIgnoreCase.Add(attributeName, enumName);
+ }
+
+ if (!attributeNamesByEnumValues.ContainsKey(value))
+ {
+ attributeNamesByEnumValues.Add(value, attributeName);
+ }
+ }
+ }
+ }
+ }
+
+ /// <inheritdoc/>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var ignoreCase = memberMapData.TypeConverterOptions.EnumIgnoreCase ?? false;
+
+ if (text != null)
+ {
+ var dict = ignoreCase
+ ? enumNamesByAttributeNamesIgnoreCase
+ : enumNamesByAttributeNames;
+ if (dict.TryGetValue(text, out var name))
+ {
+ return Enum.Parse(type, name);
+ }
+ }
+
+#if NET45 || NET47 || NETSTANDARD2_0
+ try
+ {
+ return Enum.Parse(type, text, ignoreCase);
+ }
+ catch
+ {
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+#else
+ if (Enum.TryParse(type, text, ignoreCase, out var value))
+ {
+ return value;
+ }
+ else
+ {
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+#endif
+ }
+
+ /// <inheritdoc/>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ if (value != null && attributeNamesByEnumValues.TryGetValue(value, out var name))
+ {
+ return name;
+ }
+
+ return base.ConvertToString(value, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverterFactory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverterFactory.cs
new file mode 100644
index 0000000..5918552
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverterFactory.cs
@@ -0,0 +1,35 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <inheritdoc />
+ public class EnumConverterFactory : ITypeConverterFactory
+ {
+ /// <inheritdoc />
+ public bool CanCreate(Type type)
+ {
+ return typeof(Enum).IsAssignableFrom(type);
+ }
+
+ /// <inheritdoc />
+ public bool Create(Type type, TypeConverterCache cache, out ITypeConverter typeConverter)
+ {
+ if (cache.Contains(typeof(Enum)))
+ {
+ // If the user has registered a converter for the generic Enum type,
+ // that converter will be used as a default for all enums.
+ typeConverter = cache.GetConverter<Enum>();
+
+ return false;
+ }
+
+ typeConverter = new EnumConverter(type);
+
+ return true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumerableConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumerableConverter.cs
new file mode 100644
index 0000000..0a6a06d
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumerableConverter.cs
@@ -0,0 +1,48 @@
+// Copyright 2009-2022 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.Collections;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Throws an exception when used. This is here so that it's apparent
+ /// that there is no support for <see cref="IEnumerable"/> type conversion. A custom
+ /// converter will need to be created to have a field convert to and
+ /// from an IEnumerable.
+ /// </summary>
+ public class EnumerableConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Throws an exception.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var message = "Converting IEnumerable types is not supported for a single field. " +
+ "If you want to do this, create your own ITypeConverter and register " +
+ "it in the TypeConverterFactory by calling AddConverter.";
+ throw new TypeConverterException(this, memberMapData, text, row.Context, message);
+ }
+
+ /// <summary>
+ /// Throws an exception.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ var message = "Converting IEnumerable types is not supported for a single field. " +
+ "If you want to do this, create your own ITypeConverter and register " +
+ "it in the TypeConverterFactory by calling AddConverter.";
+ throw new TypeConverterException(this, memberMapData, value, row.Context, message);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/GuidConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/GuidConverter.cs
new file mode 100644
index 0000000..7639201
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/GuidConverter.cs
@@ -0,0 +1,32 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="Guid"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class GuidConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text == null)
+ {
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+
+ return new Guid(text);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryConverter.cs
new file mode 100644
index 0000000..830756f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryConverter.cs
@@ -0,0 +1,65 @@
+// Copyright 2009-2022 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.Collections;
+using System.Collections.Generic;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="IDictionary"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class IDictionaryConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ var dictionary = value as IDictionary;
+ if (dictionary == null)
+ {
+ return base.ConvertToString(value, row, memberMapData);
+ }
+
+ foreach (DictionaryEntry entry in dictionary)
+ {
+ row.WriteField(entry.Value);
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var dictionary = new Dictionary<string, string>();
+
+ var indexEnd = memberMapData.IndexEnd < memberMapData.Index
+ ? row.Parser.Count - 1
+ : memberMapData.IndexEnd;
+
+ for (var i = memberMapData.Index; i <= indexEnd; i++)
+ {
+ if (row.TryGetField(i, out string field))
+ {
+ dictionary.Add(row.HeaderRecord[i], field);
+ }
+ }
+
+ return dictionary;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryGenericConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryGenericConverter.cs
new file mode 100644
index 0000000..5c2dea2
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryGenericConverter.cs
@@ -0,0 +1,46 @@
+// Copyright 2009-2022 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.Collections;
+using System.Collections.Generic;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="IDictionary{TKey, TValue}"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class IDictionaryGenericConverter : IDictionaryConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var keyType = memberMapData.Member.MemberType().GetGenericArguments()[0];
+ var valueType = memberMapData.Member.MemberType().GetGenericArguments()[1];
+ var dictionaryType = typeof(Dictionary<,>);
+ dictionaryType = dictionaryType.MakeGenericType(keyType, valueType);
+ var dictionary = (IDictionary)ObjectResolver.Current.Resolve(dictionaryType);
+ var converter = row.Context.TypeConverterCache.GetConverter(valueType);
+
+ var indexEnd = memberMapData.IndexEnd < memberMapData.Index
+ ? row.Parser.Count - 1
+ : memberMapData.IndexEnd;
+
+ for (var i = memberMapData.Index; i <= indexEnd; i++)
+ {
+ var field = converter.ConvertFromString(row.GetField(i), row, memberMapData);
+
+ dictionary.Add(row.HeaderRecord[i], field);
+ }
+
+ return dictionary;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableConverter.cs
new file mode 100644
index 0000000..45ef579
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableConverter.cs
@@ -0,0 +1,85 @@
+// Copyright 2009-2022 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.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="IEnumerable"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class IEnumerableConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row"></param>
+ /// <param name="memberMapData"></param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ var list = value as IEnumerable;
+ if (list == null)
+ {
+ return base.ConvertToString(value, row, memberMapData);
+ }
+
+ foreach (var item in list)
+ {
+ row.WriteField(item.ToString());
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var list = new List<string>();
+
+ if (memberMapData.IsNameSet || row.Configuration.HasHeaderRecord && !memberMapData.IsIndexSet)
+ {
+ // Use the name.
+ var nameIndex = 0;
+ while (true)
+ {
+ if (!row.TryGetField(memberMapData.Names.FirstOrDefault(), nameIndex, out string field))
+ {
+ break;
+ }
+
+ list.Add(field);
+ nameIndex++;
+ }
+ }
+ else
+ {
+ // Use the index.
+ var indexEnd = memberMapData.IndexEnd < memberMapData.Index
+ ? row.Parser.Count - 1
+ : memberMapData.IndexEnd;
+
+ for (var i = memberMapData.Index; i <= indexEnd; i++)
+ {
+ if (row.TryGetField(i, out string field))
+ {
+ list.Add(field);
+ }
+ }
+ }
+
+ return list;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableGenericConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableGenericConverter.cs
new file mode 100644
index 0000000..6718f31
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableGenericConverter.cs
@@ -0,0 +1,65 @@
+// Copyright 2009-2022 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.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="IEnumerable{T}"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class IEnumerableGenericConverter : IEnumerableConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var type = memberMapData.Member.MemberType().GetGenericArguments()[0];
+ var listType = typeof(List<>);
+ listType = listType.MakeGenericType(type);
+ var list = (IList)ObjectResolver.Current.Resolve(listType);
+ var converter = row.Context.TypeConverterCache.GetConverter(type);
+
+ if (memberMapData.IsNameSet || row.Configuration.HasHeaderRecord && !memberMapData.IsIndexSet)
+ {
+ // Use the name.
+ var nameIndex = 0;
+ while (true)
+ {
+ if (!row.TryGetField(type, memberMapData.Names.FirstOrDefault(), nameIndex, out var field))
+ {
+ break;
+ }
+
+ list.Add(field);
+ nameIndex++;
+ }
+ }
+ else
+ {
+ // Use the index.
+ var indexEnd = memberMapData.IndexEnd < memberMapData.Index
+ ? row.Parser.Count - 1
+ : memberMapData.IndexEnd;
+
+ for (var i = memberMapData.Index; i <= indexEnd; i++)
+ {
+ var field = converter.ConvertFromString(row.GetField(i), row, memberMapData);
+
+ list.Add(field);
+ }
+ }
+
+ return list;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverter.cs
new file mode 100644
index 0000000..5eb5961
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverter.cs
@@ -0,0 +1,32 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts objects to and from strings.
+ /// </summary>
+ public interface ITypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData);
+
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverterFactory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverterFactory.cs
new file mode 100644
index 0000000..67fbda9
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverterFactory.cs
@@ -0,0 +1,33 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Produces <see cref="ITypeConverter"/> for the specified <see cref="System.Type"/>
+ /// </summary>
+ public interface ITypeConverterFactory
+ {
+ /// <summary>
+ /// Determines if the factory can create a type converter for the given type.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> to be checked</param>
+ /// <returns><c>true</c> if the factory can create the type, otherwise <c>false</c>.</returns>
+ bool CanCreate(Type type);
+
+ /// <summary>
+ /// Creates a type converter for the given type and assigns it to the given out typeConverter parameter.
+ /// </summary>
+ /// <param name="type">The type to create the converter for.</param>
+ /// <param name="cache">The type converter cache.</param>
+ /// <param name="typeConverter">The parameter to set the converter to.</param>
+ /// <returns><c>true</c> if the converter should be added to the cache, otherwise <c>false</c>.</returns>
+ bool Create(Type type, TypeConverterCache cache, out ITypeConverter typeConverter);
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int16Converter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int16Converter.cs
new file mode 100644
index 0000000..630559f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int16Converter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="short"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class Int16Converter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (short.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var s))
+ {
+ return s;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int32Converter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int32Converter.cs
new file mode 100644
index 0000000..61b0f9c
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int32Converter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="int"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class Int32Converter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (int.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var i))
+ {
+ return i;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int64Converter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int64Converter.cs
new file mode 100644
index 0000000..47f717d
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int64Converter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts an <see cref="long"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class Int64Converter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (long.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var l))
+ {
+ return l;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverter.cs
new file mode 100644
index 0000000..89ce969
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverter.cs
@@ -0,0 +1,94 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="Nullable{T}"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class NullableConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Gets the type of the nullable.
+ /// </summary>
+ /// <value>
+ /// The type of the nullable.
+ /// </value>
+ public Type NullableType { get; private set; }
+
+ /// <summary>
+ /// Gets the underlying type of the nullable.
+ /// </summary>
+ /// <value>
+ /// The underlying type.
+ /// </value>
+ public Type UnderlyingType { get; private set; }
+
+ /// <summary>
+ /// Gets the type converter for the underlying type.
+ /// </summary>
+ /// <value>
+ /// The type converter.
+ /// </value>
+ public ITypeConverter UnderlyingTypeConverter { get; private set; }
+
+ /// <summary>
+ /// Creates a new <see cref="NullableConverter"/> for the given <see cref="Nullable{T}"/> <see cref="Type"/>.
+ /// </summary>
+ /// <param name="type">The nullable type.</param>
+ /// <param name="typeConverterFactory">The type converter factory.</param>
+ /// <exception cref="System.ArgumentException">type is not a nullable type.</exception>
+ public NullableConverter(Type type, TypeConverterCache typeConverterFactory)
+ {
+ NullableType = type;
+ UnderlyingType = Nullable.GetUnderlyingType(type);
+ if (UnderlyingType == null)
+ {
+ throw new ArgumentException("type is not a nullable type.");
+ }
+
+ UnderlyingTypeConverter = typeConverterFactory.GetConverter(UnderlyingType);
+ }
+
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return null;
+ }
+
+ foreach (var nullValue in memberMapData.TypeConverterOptions.NullValues)
+ {
+ if (text == nullValue)
+ {
+ return null;
+ }
+ }
+
+ return UnderlyingTypeConverter.ConvertFromString(text, row, memberMapData);
+ }
+
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row"></param>
+ /// <param name="memberMapData"></param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ return UnderlyingTypeConverter.ConvertToString(value, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverterFactory.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverterFactory.cs
new file mode 100644
index 0000000..2991348
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverterFactory.cs
@@ -0,0 +1,28 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <inheritdoc />
+ public class NullableConverterFactory : ITypeConverterFactory
+ {
+ /// <inheritdoc />
+ public bool CanCreate(Type type)
+ {
+ return (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
+ }
+
+ /// <inheritdoc />
+ public bool Create(Type type, TypeConverterCache cache, out ITypeConverter typeConverter)
+ {
+ typeConverter = new NullableConverter(type, cache);
+
+ return true;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SByteConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SByteConverter.cs
new file mode 100644
index 0000000..816a58a
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SByteConverter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="sbyte"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class SByteConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (sbyte.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var sb))
+ {
+ return sb;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SingleConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SingleConverter.cs
new file mode 100644
index 0000000..c6a8ecc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SingleConverter.cs
@@ -0,0 +1,57 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+using System;
+using System.Linq;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="Single"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class SingleConverter : DefaultTypeConverter
+ {
+ private Lazy<string> defaultFormat = new Lazy<string>(() => float.TryParse(float.MaxValue.ToString("R"), out var _) ? "R" : "G9");
+
+ /// <summary>
+ /// Converts the object to a string.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ var format = memberMapData.TypeConverterOptions.Formats?.FirstOrDefault() ?? defaultFormat.Value;
+
+ if (value is float f)
+ {
+ return f.ToString(format, memberMapData.TypeConverterOptions.CultureInfo);
+ }
+
+ return base.ConvertToString(value, row, memberMapData);
+ }
+
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Float | NumberStyles.AllowThousands;
+
+ if (float.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var f))
+ {
+ return f;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/StringConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/StringConverter.cs
new file mode 100644
index 0000000..6196973
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/StringConverter.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="string"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class StringConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text == null)
+ {
+ return string.Empty;
+ }
+
+ foreach (var nullValue in memberMapData.TypeConverterOptions.NullValues)
+ {
+ if (text == nullValue)
+ {
+ return null;
+ }
+ }
+
+ return text;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeOnlyConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeOnlyConverter.cs
new file mode 100644
index 0000000..a877b93
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeOnlyConverter.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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
+#if NET6_0
+using CsvHelper.Configuration;
+using System;
+using System.Globalization;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="TimeOnly"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class TimeOnlyConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ if (text == null)
+ {
+ return base.ConvertFromString(null, row, memberMapData);
+ }
+
+ var formatProvider = (IFormatProvider)memberMapData.TypeConverterOptions.CultureInfo.GetFormat(typeof(DateTimeFormatInfo)) ?? memberMapData.TypeConverterOptions.CultureInfo;
+ var dateTimeStyle = memberMapData.TypeConverterOptions.DateTimeStyle ?? DateTimeStyles.None;
+
+ return memberMapData.TypeConverterOptions.Formats == null || memberMapData.TypeConverterOptions.Formats.Length == 0
+ ? TimeOnly.Parse(text, formatProvider, dateTimeStyle)
+ : TimeOnly.ParseExact(text, memberMapData.TypeConverterOptions.Formats, formatProvider, dateTimeStyle);
+ }
+ }
+}
+#endif
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeSpanConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeSpanConverter.cs
new file mode 100644
index 0000000..8424475
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeSpanConverter.cs
@@ -0,0 +1,41 @@
+// Copyright 2009-2022 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;
+using System.Globalization;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="TimeSpan"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class TimeSpanConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var formatProvider = (IFormatProvider)memberMapData.TypeConverterOptions.CultureInfo;
+
+ var timeSpanStyle = memberMapData.TypeConverterOptions.TimeSpanStyle ?? TimeSpanStyles.None;
+ if (memberMapData.TypeConverterOptions.Formats != null && TimeSpan.TryParseExact(text, memberMapData.TypeConverterOptions.Formats, formatProvider, timeSpanStyle, out var span))
+ {
+ return span;
+ }
+
+ if (memberMapData.TypeConverterOptions.Formats == null && TimeSpan.TryParse(text, formatProvider, out span))
+ {
+ return span;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverter.cs
new file mode 100644
index 0000000..4a0f428
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverter.cs
@@ -0,0 +1,52 @@
+// Copyright 2009-2022 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;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Throws an exception when used. This is here so that it's apparent
+ /// that there is no support for <see cref="Type"/> type conversion. A custom
+ /// converter will need to be created to have a field convert to and
+ /// from <see cref="Type"/>.
+ /// </summary>
+ public class TypeConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Throws an exception.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var message = "Converting System.Type is not supported. " +
+ "If you want to do this, create your own ITypeConverter and register " +
+ "it in the TypeConverterFactory by calling AddConverter.";
+ throw new TypeConverterException(this, memberMapData, text ?? string.Empty, row.Context, message);
+ }
+
+ /// <summary>
+ /// Throws an exception.
+ /// </summary>
+ /// <param name="value">The object to convert to a string.</param>
+ /// <param name="row">The <see cref="IWriterRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being written.</param>
+ /// <returns>The string representation of the object.</returns>
+ public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+ {
+ var message = "Converting System.Type is not supported. " +
+ "If you want to do this, create your own ITypeConverter and register " +
+ "it in the TypeConverterFactory by calling AddConverter.";
+ throw new TypeConverterException(this, memberMapData, value, row.Context, message);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterCache.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterCache.cs
new file mode 100644
index 0000000..2f7d4dc
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterCache.cs
@@ -0,0 +1,242 @@
+// Copyright 2009-2022 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 System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Numerics;
+using System.Reflection;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Caches <see cref="ITypeConverter"/>s for a given type.
+ /// </summary>
+ public class TypeConverterCache
+ {
+ private readonly Dictionary<Type, ITypeConverter> typeConverters = new Dictionary<Type, ITypeConverter>();
+ private readonly List<ITypeConverterFactory> typeConverterFactories = new List<ITypeConverterFactory>();
+ private readonly Dictionary<Type, ITypeConverterFactory> typeConverterFactoryCache = new Dictionary<Type, ITypeConverterFactory>();
+
+ /// <summary>
+ /// Initializes the <see cref="TypeConverterCache" /> class.
+ /// </summary>
+ public TypeConverterCache()
+ {
+ CreateDefaultConverters();
+ }
+
+ /// <summary>
+ /// Determines if there is a converter registered for the given type.
+ /// </summary>
+ /// <param name="type">The type to check.</param>
+ /// <returns><c>true</c> if the converter is registered, otherwise false.</returns>
+ public bool Contains(Type type)
+ {
+ return typeConverters.ContainsKey(type);
+ }
+
+ /// <summary>
+ /// Adds the <see cref="ITypeConverterFactory"/>.
+ /// Factories are queried in order of being added and first factory that handles the type is used for creating the <see cref="ITypeConverter"/>.
+ /// </summary>
+ /// <param name="typeConverterFactory">Type converter factory</param>
+ public void AddConverterFactory(ITypeConverterFactory typeConverterFactory)
+ {
+ if (typeConverterFactory == null)
+ {
+ throw new ArgumentNullException(nameof(typeConverterFactory));
+ }
+
+ typeConverterFactories.Add(typeConverterFactory);
+ }
+
+ /// <summary>
+ /// Adds the <see cref="ITypeConverter"/> for the given <see cref="System.Type"/>.
+ /// </summary>
+ /// <param name="type">The type the converter converts.</param>
+ /// <param name="typeConverter">The type converter that converts the type.</param>
+ public void AddConverter(Type type, ITypeConverter typeConverter)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ if (typeConverter == null)
+ {
+ throw new ArgumentNullException(nameof(typeConverter));
+ }
+
+ typeConverters[type] = typeConverter;
+ }
+
+ /// <summary>
+ /// Adds the <see cref="ITypeConverter"/> for the given <see cref="System.Type"/>.
+ /// </summary>
+ /// <typeparam name="T">The type the converter converts.</typeparam>
+ /// <param name="typeConverter">The type converter that converts the type.</param>
+ public void AddConverter<T>(ITypeConverter typeConverter)
+ {
+ if (typeConverter == null)
+ {
+ throw new ArgumentNullException(nameof(typeConverter));
+ }
+
+ typeConverters[typeof(T)] = typeConverter;
+ }
+
+ /// <summary>
+ /// Adds the given <see cref="ITypeConverter"/> to all registered types.
+ /// </summary>
+ /// <param name="typeConverter">The type converter.</param>
+ public void AddConverter(ITypeConverter typeConverter)
+ {
+ foreach (var type in typeConverters.Keys)
+ {
+ typeConverters[type] = typeConverter;
+ }
+ }
+
+ /// <summary>
+ /// Removes the <see cref="ITypeConverter"/> for the given <see cref="System.Type"/>.
+ /// </summary>
+ /// <param name="type">The type to remove the converter for.</param>
+ public void RemoveConverter(Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ typeConverters.Remove(type);
+ }
+
+ /// <summary>
+ /// Removes the <see cref="ITypeConverter"/> for the given <see cref="System.Type"/>.
+ /// </summary>
+ /// <typeparam name="T">The type to remove the converter for.</typeparam>
+ public void RemoveConverter<T>()
+ {
+ RemoveConverter(typeof(T));
+ }
+
+ /// <summary>
+ /// Removes the ITypeConverterFactory.
+ /// </summary>
+ /// <param name="typeConverterFactory">The ITypeConverterFactory to remove.</param>
+ public void RemoveConverterFactory(ITypeConverterFactory typeConverterFactory)
+ {
+ typeConverterFactories.Remove(typeConverterFactory);
+ var toRemove = typeConverterFactoryCache.Where(pair => pair.Value == typeConverterFactory);
+ foreach (var pair in toRemove)
+ {
+ typeConverterFactoryCache.Remove(pair.Key);
+ }
+ }
+
+ /// <summary>
+ /// Gets the converter for the given <see cref="System.Type"/>.
+ /// </summary>
+ /// <param name="type">The type to get the converter for.</param>
+ /// <returns>The <see cref="ITypeConverter"/> for the given <see cref="System.Type"/>.</returns>
+ public ITypeConverter GetConverter(Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ if (typeConverters.TryGetValue(type, out ITypeConverter typeConverter))
+ {
+ return typeConverter;
+ }
+
+ if (!typeConverterFactoryCache.TryGetValue(type, out var factory))
+ {
+ factory = typeConverterFactories.FirstOrDefault(f => f.CanCreate(type));
+ if (factory != null)
+ {
+ typeConverterFactoryCache[type] = factory;
+ }
+ }
+
+ if (factory != null)
+ {
+ if (factory.Create(type, this, out typeConverter))
+ {
+ AddConverter(type, typeConverter);
+ }
+
+ return typeConverter;
+ }
+
+ return new DefaultTypeConverter();
+ }
+
+ /// <summary>
+ /// Gets the converter for the given member. If an attribute is
+ /// found on the member, that will be used, otherwise the cache
+ /// will be used.
+ /// </summary>
+ /// <param name="member">The member to get the converter for.</param>
+ public ITypeConverter GetConverter(MemberInfo member)
+ {
+ var typeConverterAttribute = member.GetCustomAttribute<TypeConverterAttribute>();
+ if (typeConverterAttribute != null)
+ {
+ return typeConverterAttribute.TypeConverter;
+ }
+
+ return GetConverter(member.MemberType());
+ }
+
+ /// <summary>
+ /// Gets the converter for the given <see cref="System.Type"/>.
+ /// </summary>
+ /// <typeparam name="T">The type to get the converter for.</typeparam>
+ /// <returns>The <see cref="ITypeConverter"/> for the given <see cref="System.Type"/>.</returns>
+ public ITypeConverter GetConverter<T>()
+ {
+ return GetConverter(typeof(T));
+ }
+
+ private void CreateDefaultConverters()
+ {
+ AddConverter(typeof(BigInteger), new BigIntegerConverter());
+ AddConverter(typeof(bool), new BooleanConverter());
+ AddConverter(typeof(byte), new ByteConverter());
+ AddConverter(typeof(byte[]), new ByteArrayConverter());
+ AddConverter(typeof(char), new CharConverter());
+ AddConverter(typeof(DateTime), new DateTimeConverter());
+ AddConverter(typeof(DateTimeOffset), new DateTimeOffsetConverter());
+ AddConverter(typeof(decimal), new DecimalConverter());
+ AddConverter(typeof(double), new DoubleConverter());
+ AddConverter(typeof(float), new SingleConverter());
+ AddConverter(typeof(Guid), new GuidConverter());
+ AddConverter(typeof(short), new Int16Converter());
+ AddConverter(typeof(int), new Int32Converter());
+ AddConverter(typeof(long), new Int64Converter());
+ AddConverter(typeof(sbyte), new SByteConverter());
+ AddConverter(typeof(string), new StringConverter());
+ AddConverter(typeof(TimeSpan), new TimeSpanConverter());
+ AddConverter(typeof(Type), new TypeConverter());
+ AddConverter(typeof(ushort), new UInt16Converter());
+ AddConverter(typeof(uint), new UInt32Converter());
+ AddConverter(typeof(ulong), new UInt64Converter());
+ AddConverter(typeof(Uri), new UriConverter());
+#if NET6_0
+ AddConverter(typeof(DateOnly), new DateOnlyConverter());
+ AddConverter(typeof(TimeOnly), new TimeOnlyConverter());
+#endif
+
+ AddConverterFactory(new EnumConverterFactory());
+ AddConverterFactory(new NullableConverterFactory());
+ AddConverterFactory(new CollectionConverterFactory());
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterException.cs
new file mode 100644
index 0000000..970c195
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterException.cs
@@ -0,0 +1,132 @@
+// Copyright 2009-2022 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;
+using System;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Represents errors that occur while reading a CSV file.
+ /// </summary>
+ [Serializable]
+ public class TypeConverterException : CsvHelperException
+ {
+ /// <summary>
+ /// The text used in ConvertFromString.
+ /// </summary>
+ public string Text { get; private set; }
+
+ /// <summary>
+ /// The value used in ConvertToString.
+ /// </summary>
+ public object Value { get; private set; }
+
+ /// <summary>
+ /// The type converter.
+ /// </summary>
+ public ITypeConverter TypeConverter { get; private set; }
+
+ /// <summary>
+ /// The member map data used in ConvertFromString and ConvertToString.
+ /// </summary>
+ public MemberMapData MemberMapData { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TypeConverterException"/> class.
+ /// </summary>
+ /// <param name="typeConverter">The type converter.</param>
+ /// <param name="memberMapData">The member map data.</param>
+ /// <param name="text">The text.</param>
+ /// <param name="context">The reading context.</param>
+ public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, string text, CsvContext context) : base(context)
+ {
+ TypeConverter = typeConverter;
+ MemberMapData = memberMapData;
+ Text = text;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TypeConverterException"/> class.
+ /// </summary>
+ /// <param name="typeConverter">The type converter.</param>
+ /// <param name="memberMapData">The member map data.</param>
+ /// <param name="value">The value.</param>
+ /// <param name="context">The writing context.</param>
+ public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, object value, CsvContext context) : base(context)
+ {
+ TypeConverter = typeConverter;
+ MemberMapData = memberMapData;
+ Value = value;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TypeConverterException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="typeConverter">The type converter.</param>
+ /// <param name="memberMapData">The member map data.</param>
+ /// <param name="text">The text.</param>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, string text, CsvContext context, string message) : base(context, message)
+ {
+ TypeConverter = typeConverter;
+ MemberMapData = memberMapData;
+ Text = text;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TypeConverterException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="typeConverter">The type converter.</param>
+ /// <param name="memberMapData">The member map data.</param>
+ /// <param name="value">The value.</param>
+ /// <param name="context">The writing context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, object value, CsvContext context, string message) : base(context, message)
+ {
+ TypeConverter = typeConverter;
+ MemberMapData = memberMapData;
+ Value = value;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TypeConverterException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="typeConverter">The type converter.</param>
+ /// <param name="memberMapData">The member map data.</param>
+ /// <param name="text">The text.</param>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, string text, CsvContext context, string message, Exception innerException) : base(context, message, innerException)
+ {
+ TypeConverter = typeConverter;
+ MemberMapData = memberMapData;
+ Text = text;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TypeConverterException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="typeConverter">The type converter.</param>
+ /// <param name="memberMapData">The member map data.</param>
+ /// <param name="value">The value.</param>
+ /// <param name="context">The writing context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, object value, CsvContext context, string message, Exception innerException) : base(context, message, innerException)
+ {
+ TypeConverter = typeConverter;
+ MemberMapData = memberMapData;
+ Value = value;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptions.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptions.cs
new file mode 100644
index 0000000..4a8e51f
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptions.cs
@@ -0,0 +1,157 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Options used when doing type conversion.
+ /// </summary>
+ public class TypeConverterOptions
+ {
+ private static readonly string[] defaultBooleanTrueValues = { };
+ private static readonly string[] defaultBooleanFalseValues = { };
+ private static readonly string[] defaultNullValues = { };
+
+ /// <summary>
+ /// Gets or sets the culture info.
+ /// </summary>
+ public CultureInfo CultureInfo { get; set; }
+
+ /// <summary>
+ /// Gets or sets the date time style.
+ /// </summary>
+ public DateTimeStyles? DateTimeStyle { get; set; }
+
+ /// <summary>
+ /// Gets or sets the time span style.
+ /// </summary>
+ public TimeSpanStyles? TimeSpanStyle { get; set; }
+
+ /// <summary>
+ /// Gets or sets the number style.
+ /// </summary>
+ public NumberStyles? NumberStyles { get; set; }
+
+ /// <summary>
+ /// Gets or sets the string format.
+ /// </summary>
+ public string[] Formats { get; set; }
+
+ /// <summary>
+ /// Gets or sets the <see cref="UriKind"/>.
+ /// </summary>
+ public UriKind? UriKind { get; set; }
+
+ /// <summary>
+ /// Ingore case when parsing enums. Default is false.
+ /// </summary>
+ public bool? EnumIgnoreCase { get; set; }
+
+ /// <summary>
+ /// Gets the list of values that can be
+ /// used to represent a boolean of true.
+ /// </summary>
+ public List<string> BooleanTrueValues { get; } = new List<string>(defaultBooleanTrueValues);
+
+ /// <summary>
+ /// Gets the list of values that can be
+ /// used to represent a boolean of false.
+ /// </summary>
+ public List<string> BooleanFalseValues { get; } = new List<string>(defaultBooleanFalseValues);
+
+ /// <summary>
+ /// Gets the list of values that can be used to represent a null value.
+ /// </summary>
+ public List<string> NullValues { get; } = new List<string>(defaultNullValues);
+
+ /// <summary>
+ /// Merges TypeConverterOptions by applying the values of sources in order on to each other.
+ /// The first object is the source object.
+ /// </summary>
+ /// <param name="sources">The sources that will be applied.</param>
+ /// <returns>The updated source object.</returns>
+ public static TypeConverterOptions? Merge(params TypeConverterOptions[] sources)
+ {
+ if (sources == null || sources.Length == 0)
+ {
+ return null;
+ }
+
+ var options = sources[0];
+
+ for (var i = 1; i < sources.Length; i++)
+ {
+ var source = sources[i];
+
+ if (source == null)
+ {
+ continue;
+ }
+
+ if (source.CultureInfo != null)
+ {
+ options.CultureInfo = source.CultureInfo;
+ }
+
+ if (source.DateTimeStyle != null)
+ {
+ options.DateTimeStyle = source.DateTimeStyle;
+ }
+
+ if (source.TimeSpanStyle != null)
+ {
+ options.TimeSpanStyle = source.TimeSpanStyle;
+ }
+
+ if (source.NumberStyles != null)
+ {
+ options.NumberStyles = source.NumberStyles;
+ }
+
+ if (source.Formats != null)
+ {
+ options.Formats = source.Formats;
+ }
+
+ if (source.UriKind != null)
+ {
+ options.UriKind = source.UriKind;
+ }
+
+ if (source.EnumIgnoreCase != null)
+ {
+ options.EnumIgnoreCase = source.EnumIgnoreCase;
+ }
+
+ // Only change the values if they are different than the defaults.
+ // This means there were explicit changes made to the options.
+
+ if (!defaultBooleanTrueValues.SequenceEqual(source.BooleanTrueValues))
+ {
+ options.BooleanTrueValues.Clear();
+ options.BooleanTrueValues.AddRange(source.BooleanTrueValues);
+ }
+
+ if (!defaultBooleanFalseValues.SequenceEqual(source.BooleanFalseValues))
+ {
+ options.BooleanFalseValues.Clear();
+ options.BooleanFalseValues.AddRange(source.BooleanFalseValues);
+ }
+
+ if (!defaultNullValues.SequenceEqual(source.NullValues))
+ {
+ options.NullValues.Clear();
+ options.NullValues.AddRange(source.NullValues);
+ }
+ }
+
+ return options;
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptionsCache.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptionsCache.cs
new file mode 100644
index 0000000..37e0d99
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptionsCache.cs
@@ -0,0 +1,108 @@
+// Copyright 2009-2022 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;
+using System.Collections.Generic;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Caches <see cref="TypeConverterOptions"/> for a given type.
+ /// </summary>
+ public class TypeConverterOptionsCache
+ {
+ private Dictionary<Type, TypeConverterOptions> typeConverterOptions = new Dictionary<Type, TypeConverterOptions>();
+
+ /// <summary>
+ /// Adds the <see cref="TypeConverterOptions"/> for the given <see cref="Type"/>.
+ /// </summary>
+ /// <param name="type">The type the options are for.</param>
+ /// <param name="options">The options.</param>
+ public void AddOptions(Type type, TypeConverterOptions options)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ typeConverterOptions[type] = options ?? throw new ArgumentNullException(nameof(options));
+ }
+
+ /// <summary>
+ /// Adds the <see cref="TypeConverterOptions"/> for the given <see cref="Type"/>.
+ /// </summary>
+ /// <typeparam name="T">The type the options are for.</typeparam>
+ /// <param name="options">The options.</param>
+ public void AddOptions<T>(TypeConverterOptions options)
+ {
+ AddOptions(typeof(T), options);
+ }
+
+ /// <summary>
+ /// Adds the given <see cref="TypeConverterOptions"/> to all registered types.
+ /// </summary>
+ /// <param name="options"></param>
+ public void AddOptions(TypeConverterOptions options)
+ {
+ foreach (var type in typeConverterOptions.Keys)
+ {
+ typeConverterOptions[type] = options;
+ }
+ }
+
+ /// <summary>
+ /// Removes the <see cref="TypeConverterOptions"/> for the given type.
+ /// </summary>
+ /// <param name="type">The type to remove the options for.</param>
+ public void RemoveOptions(Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ typeConverterOptions.Remove(type);
+ }
+
+ /// <summary>
+ /// Removes the <see cref="TypeConverterOptions"/> for the given type.
+ /// </summary>
+ /// <typeparam name="T">The type to remove the options for.</typeparam>
+ public void RemoveOptions<T>()
+ {
+ RemoveOptions(typeof(T));
+ }
+
+ /// <summary>
+ /// Get the <see cref="TypeConverterOptions"/> for the given <see cref="Type"/>.
+ /// </summary>
+ /// <param name="type">The type the options are for.</param>
+ /// <returns>The options for the given type.</returns>
+ public TypeConverterOptions GetOptions(Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ if (!typeConverterOptions.TryGetValue(type, out var options))
+ {
+ options = new TypeConverterOptions();
+ typeConverterOptions.Add(type, options);
+ }
+
+ return options;
+ }
+
+ /// <summary>
+ /// Get the <see cref="TypeConverterOptions"/> for the given <see cref="Type"/>.
+ /// </summary>
+ /// <typeparam name="T">The type the options are for.</typeparam>
+ /// <returns>The options for the given type.</returns>
+ public TypeConverterOptions GetOptions<T>()
+ {
+ return GetOptions(typeof(T));
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt16Converter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt16Converter.cs
new file mode 100644
index 0000000..429c1b7
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt16Converter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="ushort"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class UInt16Converter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (ushort.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var us))
+ {
+ return us;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt32Converter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt32Converter.cs
new file mode 100644
index 0000000..52c0e90
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt32Converter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="uint"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class UInt32Converter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (uint.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var ui))
+ {
+ return ui;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt64Converter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt64Converter.cs
new file mode 100644
index 0000000..c74a8e7
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt64Converter.cs
@@ -0,0 +1,34 @@
+// Copyright 2009-2022 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;
+using CsvHelper.Configuration;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="ulong"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class UInt64Converter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the string to an object.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow"/> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData"/> for the member being created.</param>
+ /// <returns>The object created from the string.</returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var numberStyle = memberMapData.TypeConverterOptions.NumberStyles ?? NumberStyles.Integer;
+
+ if (ulong.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var ul))
+ {
+ return ul;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UriConverter.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UriConverter.cs
new file mode 100644
index 0000000..3552180
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UriConverter.cs
@@ -0,0 +1,40 @@
+// Copyright 2009-2022 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;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CsvHelper.TypeConversion
+{
+ /// <summary>
+ /// Converts a <see cref="Uri"/> to and from a <see cref="string"/>.
+ /// </summary>
+ public class UriConverter : DefaultTypeConverter
+ {
+ /// <summary>
+ /// Converts the <see cref="string"/> to a <see cref="Uri"/>.
+ /// </summary>
+ /// <param name="text">The string to convert to an object.</param>
+ /// <param name="row">The <see cref="IReaderRow" /> for the current record.</param>
+ /// <param name="memberMapData">The <see cref="MemberMapData" /> for the member being created.</param>
+ /// <returns>
+ /// The <see cref="Uri"/> created from the string.
+ /// </returns>
+ public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
+ {
+ var uriKind = memberMapData.TypeConverterOptions.UriKind ?? default;
+
+ if (Uri.TryCreate(text, uriKind, out var uri))
+ {
+ return uri;
+ }
+
+ return base.ConvertFromString(text, row, memberMapData);
+ }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ValidationException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ValidationException.cs
new file mode 100644
index 0000000..f7f3267
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ValidationException.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents a user supplied validation failure.
+ /// </summary>
+ [Serializable]
+ public abstract class ValidationException : CsvHelperException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ public ValidationException(CsvContext context) : base(context) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public ValidationException(CsvContext context, string message) : base(context, message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidationException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The reading context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public ValidationException(CsvContext context, string message, Exception innerException) : base(context, message, innerException) { }
+ }
+}
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/WriterException.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/WriterException.cs
new file mode 100644
index 0000000..596fa51
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/WriterException.cs
@@ -0,0 +1,39 @@
+// Copyright 2009-2022 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;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Represents errors that occur while writing a CSV file.
+ /// </summary>
+ [Serializable]
+ public class WriterException : CsvHelperException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WriterException"/> class.
+ /// </summary>
+ /// <param name="context">The writing context.</param>
+ public WriterException(CsvContext context) : base(context) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WriterException"/> class
+ /// with a specified error message.
+ /// </summary>
+ /// <param name="context">The writing context.</param>
+ /// <param name="message">The message that describes the error.</param>
+ public WriterException(CsvContext context, string message) : base(context, message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WriterException"/> class
+ /// with a specified error message and a reference to the inner exception that
+ /// is the cause of this exception.
+ /// </summary>
+ /// <param name="context">The writing context.</param>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+ public WriterException(CsvContext context, string message, Exception innerException) : base(context, message, innerException) { }
+ }
+}