From 2a1cd4fda8a4a8e649910d16b4dfa1ce7ae63543 Mon Sep 17 00:00:00 2001 From: chai <215380520@qq.com> Date: Fri, 12 May 2023 09:24:40 +0800 Subject: *misc --- .../CsvHelper-master/src/CsvHelper/ArrayHelper.cs | 78 ++ .../src/CsvHelper/BadDataException.cs | 67 + .../Attributes/AllowCommentsAttribute.cs | 35 + .../Attributes/BooleanFalseValuesAttribute.cs | 52 + .../Attributes/BooleanTrueValuesAttribute.cs | 52 + .../Attributes/BufferSizeAttribute.cs | 36 + .../Attributes/CacheFieldsAttribute.cs | 36 + .../Configuration/Attributes/CommentAttribute.cs | 36 + .../Configuration/Attributes/ConstantAttribute.cs | 47 + .../Attributes/CountBytesAttribute.cs | 45 + .../Attributes/CultureInfoAttribute.cs | 46 + .../Attributes/DateTimeStylesAttribute.cs | 44 + .../Configuration/Attributes/DefaultAttribute.cs | 45 + .../Configuration/Attributes/DelimiterAttribute.cs | 35 + .../DetectColumnCountChangesAttribute.cs | 40 + .../Attributes/DetectDelimiterAttribute.cs | 35 + .../Attributes/DetectDelimiterValuesAttribute.cs | 37 + .../Configuration/Attributes/EncodingAttribute.cs | 36 + .../Attributes/EnumIgnoreCaseAttribute.cs | 41 + .../Configuration/Attributes/EscapeAttribute.cs | 35 + .../ExceptionMessagesContainRawDataAttribute.cs | 39 + .../Configuration/Attributes/FormatAttribute.cs | 50 + .../Attributes/HasHeaderRecordAttribute.cs | 35 + .../Attributes/HeaderPrefixAttribute.cs | 73 + .../Configuration/Attributes/IClassMapper.cs | 19 + .../Configuration/Attributes/IMemberMapper.cs | 20 + .../Attributes/IMemberReferenceMapper.cs | 20 + .../Configuration/Attributes/IParameterMapper.cs | 24 + .../Attributes/IParameterReferenceMapper.cs | 24 + .../Configuration/Attributes/IgnoreAttribute.cs | 41 + .../Attributes/IgnoreBaseAttribute.cs | 20 + .../Attributes/IgnoreBlankLinesAttribute.cs | 35 + .../Attributes/IgnoreReferencesAttribute.cs | 41 + .../Attributes/IncludePrivateMembersAttribute.cs | 35 + .../Configuration/Attributes/IndexAttribute.cs | 57 + .../Attributes/InjectionCharactersAttribute.cs | 37 + .../InjectionEscapeCharacterAttribute.cs | 35 + .../Attributes/InjectionOptionsAttribute.cs | 35 + .../LineBreakInQuotedFieldIsBadDataAttribute.cs | 39 + .../Attributes/MaxFieldSizeAttribute.cs | 40 + .../Attributes/MemberTypesAttribute.cs | 40 + .../Configuration/Attributes/ModeAttribute.cs | 38 + .../Configuration/Attributes/NameAttribute.cs | 77 ++ .../Configuration/Attributes/NameIndexAttribute.cs | 45 + .../Configuration/Attributes/NewLineAttribute.cs | 39 + .../Attributes/NullValuesAttribute.cs | 52 + .../Attributes/NumberStylesAttribute.cs | 44 + .../Configuration/Attributes/OptionalAttribute.cs | 27 + .../Attributes/ProcessFieldBufferSizeAttribute.cs | 36 + .../Configuration/Attributes/QuoteAttribute.cs | 35 + .../Attributes/TrimOptionsAttribute.cs | 35 + .../Attributes/TypeConverterAttribute.cs | 57 + ...UseNewObjectForNullReferenceMembersAttribute.cs | 47 + .../Attributes/WhiteSpaceCharsAttribute.cs | 41 + .../src/CsvHelper/Configuration/ClassMap.cs | 648 +++++++++ .../src/CsvHelper/Configuration/ClassMapBuilder.cs | 432 ++++++ .../CsvHelper/Configuration/ClassMapCollection.cs | 188 +++ .../src/CsvHelper/Configuration/ClassMap`1.cs | 112 ++ .../Configuration/ConfigurationException.cs | 36 + .../Configuration/ConfigurationFunctions.cs | 267 ++++ .../CsvHelper/Configuration/CsvConfiguration.cs | 240 ++++ .../CsvHelper/Configuration/DefaultClassMap`1.cs | 15 + .../Configuration/IParserConfiguration.cs | 176 +++ .../Configuration/IReaderConfiguration.cs | 111 ++ .../Configuration/IWriterConfiguration.cs | 168 +++ .../CsvHelper/Configuration/InjectionOptions.cs | 31 + .../src/CsvHelper/Configuration/MemberMap.cs | 244 ++++ .../CsvHelper/Configuration/MemberMapCollection.cs | 247 ++++ .../CsvHelper/Configuration/MemberMapComparer.cs | 74 + .../src/CsvHelper/Configuration/MemberMapData.cs | 167 +++ .../Configuration/MemberMapTypeConverterOption.cs | 167 +++ .../src/CsvHelper/Configuration/MemberMap`1.cs | 270 ++++ .../Configuration/MemberNameCollection.cs | 98 ++ .../CsvHelper/Configuration/MemberReferenceMap.cs | 68 + .../Configuration/MemberReferenceMapCollection.cs | 164 +++ .../Configuration/MemberReferenceMapData.cs | 68 + .../src/CsvHelper/Configuration/MemberTypes.cs | 32 + .../src/CsvHelper/Configuration/ParameterMap.cs | 212 +++ .../CsvHelper/Configuration/ParameterMapData.cs | 106 ++ .../ParameterMapTypeConverterOption.cs | 160 +++ .../Configuration/ParameterReferenceMap.cs | 66 + .../Configuration/ParameterReferenceMapData.cs | 70 + .../src/CsvHelper/Configuration/TrimOptions.cs | 30 + .../CsvHelper-master/src/CsvHelper/CsvContext.cs | 202 +++ .../src/CsvHelper/CsvDataReader.cs | 387 ++++++ .../src/CsvHelper/CsvHelper.csproj | 92 ++ .../CsvHelper/CsvHelper.net45.v3.ncrunchproject | 5 + .../CsvHelper/CsvHelper.net47.v3.ncrunchproject | 5 + .../CsvHelper/CsvHelper.net5.0.v3.ncrunchproject | 5 + .../CsvHelper/CsvHelper.net50.v3.ncrunchproject | 5 + .../CsvHelper/CsvHelper.net6.0.v3.ncrunchproject | 5 + .../CsvHelper/CsvHelper.net60.v3.ncrunchproject | 5 + .../CsvHelper.netstandard2.0.v3.ncrunchproject | 5 + .../CsvHelper.netstandard2.1.v3.ncrunchproject | 5 + .../CsvHelper-master/src/CsvHelper/CsvHelper.snk | Bin 0 -> 596 bytes .../src/CsvHelper/CsvHelperException.cs | 144 ++ .../CsvHelper-master/src/CsvHelper/CsvMode.cs | 43 + .../CsvHelper-master/src/CsvHelper/CsvParser.cs | 1194 ++++++++++++++++ .../CsvHelper-master/src/CsvHelper/CsvReader.cs | 1419 ++++++++++++++++++++ .../CsvHelper-master/src/CsvHelper/CsvWriter.cs | 842 ++++++++++++ .../src/CsvHelper/Delegates/BadDataFound.cs | 52 + .../src/CsvHelper/Delegates/ConvertFromString.cs | 40 + .../src/CsvHelper/Delegates/ConvertToString.cs | 41 + .../src/CsvHelper/Delegates/GetConstructor.cs | 38 + .../src/CsvHelper/Delegates/GetDelimiter.cs | 44 + .../CsvHelper/Delegates/GetDynamicPropertyName.cs | 44 + .../src/CsvHelper/Delegates/HeaderValidated.cs | 46 + .../src/CsvHelper/Delegates/MissingFieldFound.cs | 53 + .../CsvHelper/Delegates/PrepareHeaderForMatch.cs | 47 + .../Delegates/ReadingExceptionOccurred.cs | 40 + .../CsvHelper/Delegates/ReferenceHeaderPrefix.cs | 44 + .../src/CsvHelper/Delegates/ShouldQuote.cs | 51 + .../src/CsvHelper/Delegates/ShouldSkipRecord.cs | 37 + .../Delegates/ShouldUseConstructorParameters.cs | 38 + .../src/CsvHelper/Delegates/Validate.cs | 53 + .../src/CsvHelper/EnumerableExtensions.cs | 27 + .../CsvHelper/Expressions/DynamicRecordCreator.cs | 61 + .../CsvHelper/Expressions/DynamicRecordWriter.cs | 75 ++ .../Expressions/ExpandoObjectRecordWriter.cs | 49 + .../src/CsvHelper/Expressions/ExpressionManager.cs | 490 +++++++ .../CsvHelper/Expressions/ObjectRecordCreator.cs | 66 + .../CsvHelper/Expressions/ObjectRecordWriter.cs | 124 ++ .../Expressions/PrimitiveRecordCreator.cs | 49 + .../CsvHelper/Expressions/PrimitiveRecordWriter.cs | 57 + .../src/CsvHelper/Expressions/RecordCreator.cs | 107 ++ .../CsvHelper/Expressions/RecordCreatorFactory.cs | 51 + .../src/CsvHelper/Expressions/RecordHydrator.cs | 126 ++ .../src/CsvHelper/Expressions/RecordManager.cs | 80 ++ .../src/CsvHelper/Expressions/RecordWriter.cs | 109 ++ .../CsvHelper/Expressions/RecordWriterFactory.cs | 61 + .../CsvHelper-master/src/CsvHelper/Factory.cs | 108 ++ .../CsvHelper-master/src/CsvHelper/FieldCache.cs | 137 ++ .../src/CsvHelper/FieldValidationException.cs | 55 + .../src/CsvHelper/HeaderValidationException.cs | 55 + .../CsvHelper-master/src/CsvHelper/IFactory.cs | 85 ++ .../src/CsvHelper/IObjectResolver.cs | 57 + .../CsvHelper-master/src/CsvHelper/IParser.cs | 89 ++ .../CsvHelper-master/src/CsvHelper/IReader.cs | 126 ++ .../CsvHelper-master/src/CsvHelper/IReaderRow.cs | 428 ++++++ .../CsvHelper-master/src/CsvHelper/IWriter.cs | 86 ++ .../CsvHelper-master/src/CsvHelper/IWriterRow.cs | 135 ++ ThirdParty/CsvHelper-master/src/CsvHelper/Icon.png | Bin 0 -> 728 bytes .../src/CsvHelper/InvalidHeader.cs | 28 + .../src/CsvHelper/LinkedListExtensions.cs | 29 + .../src/CsvHelper/MaxFieldSizeException.cs | 39 + .../src/CsvHelper/MissingFieldException.cs | 40 + .../src/CsvHelper/ObjectCreator.cs | 218 +++ .../src/CsvHelper/ObjectResolver.cs | 143 ++ .../src/CsvHelper/ParserException.cs | 39 + .../src/CsvHelper/Properties/AssemblyInfo.cs | 13 + .../src/CsvHelper/ReaderException.cs | 39 + .../src/CsvHelper/ReflectionExtensions.cs | 155 +++ .../src/CsvHelper/ReflectionHelper.cs | 204 +++ .../src/CsvHelper/TypeConversion/ArrayConverter.cs | 73 + .../TypeConversion/BigIntegerConverter.cs | 57 + .../CsvHelper/TypeConversion/BooleanConverter.cs | 72 + .../CsvHelper/TypeConversion/ByteArrayConverter.cs | 126 ++ .../TypeConversion/ByteArrayConverterOptions.cs | 44 + .../src/CsvHelper/TypeConversion/ByteConverter.cs | 34 + .../src/CsvHelper/TypeConversion/CharConverter.cs | 36 + .../TypeConversion/CollectionConverterFactory.cs | 175 +++ .../TypeConversion/CollectionGenericConverter.cs | 64 + .../CsvHelper/TypeConversion/DateOnlyConverter.cs | 40 + .../CsvHelper/TypeConversion/DateTimeConverter.cs | 43 + .../TypeConversion/DateTimeOffsetConverter.cs | 43 + .../CsvHelper/TypeConversion/DecimalConverter.cs | 34 + .../TypeConversion/DefaultTypeConverter.cs | 62 + .../CsvHelper/TypeConversion/DoubleConverter.cs | 57 + .../src/CsvHelper/TypeConversion/EnumConverter.cs | 121 ++ .../TypeConversion/EnumConverterFactory.cs | 35 + .../TypeConversion/EnumerableConverter.cs | 48 + .../src/CsvHelper/TypeConversion/GuidConverter.cs | 32 + .../TypeConversion/IDictionaryConverter.cs | 65 + .../TypeConversion/IDictionaryGenericConverter.cs | 46 + .../TypeConversion/IEnumerableConverter.cs | 85 ++ .../TypeConversion/IEnumerableGenericConverter.cs | 65 + .../src/CsvHelper/TypeConversion/ITypeConverter.cs | 32 + .../TypeConversion/ITypeConverterFactory.cs | 33 + .../src/CsvHelper/TypeConversion/Int16Converter.cs | 34 + .../src/CsvHelper/TypeConversion/Int32Converter.cs | 34 + .../src/CsvHelper/TypeConversion/Int64Converter.cs | 34 + .../CsvHelper/TypeConversion/NullableConverter.cs | 94 ++ .../TypeConversion/NullableConverterFactory.cs | 28 + .../src/CsvHelper/TypeConversion/SByteConverter.cs | 34 + .../CsvHelper/TypeConversion/SingleConverter.cs | 57 + .../CsvHelper/TypeConversion/StringConverter.cs | 39 + .../CsvHelper/TypeConversion/TimeOnlyConverter.cs | 40 + .../CsvHelper/TypeConversion/TimeSpanConverter.cs | 41 + .../src/CsvHelper/TypeConversion/TypeConverter.cs | 52 + .../CsvHelper/TypeConversion/TypeConverterCache.cs | 242 ++++ .../TypeConversion/TypeConverterException.cs | 132 ++ .../TypeConversion/TypeConverterOptions.cs | 157 +++ .../TypeConversion/TypeConverterOptionsCache.cs | 108 ++ .../CsvHelper/TypeConversion/UInt16Converter.cs | 34 + .../CsvHelper/TypeConversion/UInt32Converter.cs | 34 + .../CsvHelper/TypeConversion/UInt64Converter.cs | 34 + .../src/CsvHelper/TypeConversion/UriConverter.cs | 40 + .../src/CsvHelper/ValidationException.cs | 39 + .../src/CsvHelper/WriterException.cs | 39 + 199 files changed, 18616 insertions(+) create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ArrayHelper.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/BadDataException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/AllowCommentsAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanFalseValuesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BooleanTrueValuesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/BufferSizeAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CacheFieldsAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CommentAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ConstantAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CountBytesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/CultureInfoAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DateTimeStylesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DefaultAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DelimiterAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectColumnCountChangesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/DetectDelimiterValuesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EncodingAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EnumIgnoreCaseAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/EscapeAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ExceptionMessagesContainRawDataAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/FormatAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HasHeaderRecordAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/HeaderPrefixAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IClassMapper.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberMapper.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IMemberReferenceMapper.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterMapper.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IParameterReferenceMapper.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBaseAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreBlankLinesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IgnoreReferencesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IncludePrivateMembersAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/IndexAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionCharactersAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionEscapeCharacterAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/InjectionOptionsAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/LineBreakInQuotedFieldIsBadDataAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MaxFieldSizeAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/MemberTypesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ModeAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NameIndexAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NewLineAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NullValuesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/NumberStylesAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/OptionalAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/ProcessFieldBufferSizeAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/QuoteAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TrimOptionsAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/TypeConverterAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/UseNewObjectForNullReferenceMembersAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/Attributes/WhiteSpaceCharsAttribute.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapBuilder.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMapCollection.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ClassMap`1.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ConfigurationFunctions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/CsvConfiguration.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/DefaultClassMap`1.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IParserConfiguration.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IReaderConfiguration.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/IWriterConfiguration.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/InjectionOptions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapCollection.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapComparer.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapData.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMapTypeConverterOption.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberMap`1.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberNameCollection.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMap.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapCollection.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberReferenceMapData.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/MemberTypes.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMap.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapData.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterMapTypeConverterOption.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMap.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/ParameterReferenceMapData.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Configuration/TrimOptions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvContext.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvDataReader.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.csproj create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net45.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net47.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net5.0.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net50.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net6.0.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.net60.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.0.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.netstandard2.1.v3.ncrunchproject create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.snk create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelperException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvMode.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvParser.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvReader.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/CsvWriter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/BadDataFound.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertFromString.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ConvertToString.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetConstructor.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDelimiter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/GetDynamicPropertyName.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/HeaderValidated.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/MissingFieldFound.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/PrepareHeaderForMatch.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReadingExceptionOccurred.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ReferenceHeaderPrefix.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldQuote.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldSkipRecord.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/ShouldUseConstructorParameters.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Delegates/Validate.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/EnumerableExtensions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordCreator.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/DynamicRecordWriter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ExpressionManager.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordCreator.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/ObjectRecordWriter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordCreator.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/PrimitiveRecordWriter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreator.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordCreatorFactory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordHydrator.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordManager.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Expressions/RecordWriterFactory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Factory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/FieldCache.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/FieldValidationException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/HeaderValidationException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/IFactory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/IObjectResolver.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/IParser.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/IReader.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/IReaderRow.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/IWriter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/IWriterRow.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Icon.png create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/InvalidHeader.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/LinkedListExtensions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/MaxFieldSizeException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/MissingFieldException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ObjectCreator.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ObjectResolver.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ParserException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/Properties/AssemblyInfo.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ReaderException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionExtensions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ArrayConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BigIntegerConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/BooleanConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteArrayConverterOptions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ByteConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CharConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionConverterFactory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/CollectionGenericConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateOnlyConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DateTimeOffsetConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DecimalConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DefaultTypeConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/DoubleConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumConverterFactory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/EnumerableConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/GuidConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IDictionaryGenericConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/IEnumerableGenericConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/ITypeConverterFactory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int16Converter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int32Converter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/Int64Converter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/NullableConverterFactory.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SByteConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/SingleConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/StringConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeOnlyConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TimeSpanConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterCache.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptions.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/TypeConverterOptionsCache.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt16Converter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt32Converter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UInt64Converter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/TypeConversion/UriConverter.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/ValidationException.cs create mode 100644 ThirdParty/CsvHelper-master/src/CsvHelper/WriterException.cs (limited to 'ThirdParty/CsvHelper-master/src/CsvHelper') 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 +{ + /// + /// Methods to help with arrays. + /// + public static class ArrayHelper + { + /// + /// Trims the characters off the start and end of the buffer + /// by updating the start and length arguments. + /// + /// The buffer. + /// The start. + /// The length. + /// The characters to trim. + [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--; + } + } + + /// + /// Determines whether this given array contains the given character. + /// + /// The array to search. + /// The character to look for. + /// + /// true if the array contains the characters, otherwise false. + /// + [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 +{ + /// + /// Represents errors that occur due to bad data. + /// + [Serializable] + public class BadDataException : CsvHelperException + { + /// + /// The full field unedited. + /// + public readonly string Field; + + /// + /// The full row unedited. + /// + public readonly string RawRecord; + + /// + /// Initializes a new instance of the class. + /// + /// The full field unedited. + /// The full row unedited. + /// The reading context. + public BadDataException(string field, string rawRecord, CsvContext context) : base(context) + { + Field = field; + RawRecord = rawRecord; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The full field unedited. + /// The full row unedited. + /// The reading context. + /// The message that describes the error. + public BadDataException(string field, string rawRecord, CsvContext context, string message) : base(context, message) + { + Field = field; + RawRecord = rawRecord; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The full field unedited. + /// The full row unedited. + /// The reading context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public BadDataException(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 +{ + /// + /// A value indicating if comments are allowed. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class AllowCommentsAttribute : Attribute, IClassMapper + { + /// + /// Gets a value indicating if comments are allowed. + /// + public bool AllowComments { get; private set; } + + /// + /// A value indicating if comments are allowed. + /// + /// The value indicating id comments are allowed. + public AllowCommentsAttribute(bool allowComments) + { + AllowComments = allowComments; + } + + /// + 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 +{ + /// + /// The string values used to represent a boolean false when converting. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class BooleanFalseValuesAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the false values. + /// + public string[] FalseValues { get; private set; } + + /// + /// The string values used to represent a boolean false when converting. + /// + /// The false values. + public BooleanFalseValuesAttribute(string falseValue) + { + FalseValues = new string[] { falseValue }; + } + + /// + /// The string values used to represent a boolean false when converting. + /// + /// The false values. + public BooleanFalseValuesAttribute(params string[] falseValues) + { + FalseValues = falseValues; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.BooleanFalseValues.Clear(); + memberMap.Data.TypeConverterOptions.BooleanFalseValues.AddRange(FalseValues); + } + + /// + 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 +{ + /// + /// The string values used to represent a boolean true when converting. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class BooleanTrueValuesAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the true values. + /// + public string[] TrueValues { get; private set; } + + /// + /// The string values used to represent a boolean true when converting. + /// + /// + public BooleanTrueValuesAttribute(string trueValue) + { + TrueValues = new string[] { trueValue }; + } + + /// + /// The string values used to represent a boolean true when converting. + /// + /// + public BooleanTrueValuesAttribute(params string[] trueValues) + { + TrueValues = trueValues; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.BooleanTrueValues.Clear(); + memberMap.Data.TypeConverterOptions.BooleanTrueValues.AddRange(TrueValues); + } + + /// + 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 +{ + /// + /// The size of the buffer used for parsing and writing CSV files. + /// Default is 0x1000. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class BufferSizeAttribute : Attribute, IClassMapper + { + /// + /// The buffer size. + /// + public int BufferSize { get; private set; } + + /// + /// The size of the buffer used for parsing and writing CSV files. + /// + /// + public BufferSizeAttribute(int bufferSize) + { + BufferSize = bufferSize; + } + + /// + 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 +{ + /// + /// Cache fields that are created when parsing. + /// Default is false. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class CacheFieldsAttribute : Attribute, IClassMapper + { + /// + /// Cache fields that are created when parsing. + /// + public bool CacheFields { get; private set; } + + /// + /// Cache fields that are created when parsing. + /// + /// + public CacheFieldsAttribute(bool cacheFields) + { + CacheFields = cacheFields; + } + + /// + 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 +{ + /// + /// The character used to denote a line that is commented out. + /// Default is #. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class CommentAttribute : Attribute, IClassMapper + { + /// + /// Gets the character used to denote a line that is commented out. + /// + public char Comment { get; private set; } + + /// + /// The character used to denote a line that is commented out. + /// + /// The comment character. + public CommentAttribute(char comment) + { + Comment = comment; + } + + /// + 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 +{ + /// + /// 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. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class ConstantAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the constant. + /// + public object Constant { get; private set; } + + /// + /// 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. + /// + /// The constant. + public ConstantAttribute(object constant) + { + Constant = constant; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.Constant = Constant; + memberMap.Data.IsConstantSet = true; + } + + /// + 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 +{ + /// + /// A value indicating whether the number of bytes should + /// be counted while parsing. Default is false. This will slow down parsing + /// because it needs to get the byte count of every char for the given encoding. + /// The needs to be set correctly for this to be accurate. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class CountBytesAttribute : Attribute, IClassMapper + { + /// + /// A value indicating whether the number of bytes should + /// be counted while parsing. Default is false. This will slow down parsing + /// because it needs to get the byte count of every char for the given encoding. + /// The needs to be set correctly for this to be accurate. + /// + public bool CountBytes { get; private set; } + + /// + /// A value indicating whether the number of bytes should + /// be counted while parsing. Default is false. This will slow down parsing + /// because it needs to get the byte count of every char for the given encoding. + /// The needs to be set correctly for this to be accurate. + /// + /// + public CountBytesAttribute(bool countBytes) + { + CountBytes = countBytes; + } + + /// + 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 +{ + /// + /// The used when type converting. + /// This will override the global + /// setting. Or set the same if the attribute is specified on class level. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class CultureInfoAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the culture info. + /// + public CultureInfo CultureInfo { get; private set; } + + /// + /// The used when type converting. + /// This will override the global + /// setting. Or set the same if the attribute is specified on class level. + /// + /// The culture. + public CultureInfoAttribute(string culture) + { + CultureInfo = CultureInfo.GetCultureInfo(culture); + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.CultureInfo = CultureInfo; + } + + /// + 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 +{ + /// + /// The to use when type converting. + /// This is used when doing any conversions. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class DateTimeStylesAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the date time styles. + /// + public DateTimeStyles DateTimeStyles { get; private set; } + + /// + /// The to use when type converting. + /// This is used when doing any conversions. + /// + /// The date time styles. + public DateTimeStylesAttribute(DateTimeStyles dateTimeStyles) + { + DateTimeStyles = dateTimeStyles; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.DateTimeStyle = DateTimeStyles; + } + + /// + 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 +{ + /// + /// The default value that will be used when reading when + /// the CSV field is empty. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class DefaultAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the default value. + /// + public object Default { get; private set; } + + /// + /// The default value that will be used when reading when + /// the CSV field is empty. + /// + /// The default value + public DefaultAttribute(object defaultValue) + { + Default = defaultValue; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.Default = Default; + memberMap.Data.IsDefaultSet = true; + } + + /// + 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 +{ + /// + /// The delimiter used to separate fields. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class DelimiterAttribute : Attribute, IClassMapper + { + /// + /// Gets the delimiter. + /// + public string Delimiter { get; private set; } + + /// + /// The delimiter used to separate fields. + /// + /// The delimiter. + public DelimiterAttribute(string delimiter) + { + Delimiter = delimiter; + } + + /// + 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 +{ + /// + /// A value indicating whether changes in the column + /// count should be detected. If true, a + /// will be thrown if a different column count is detected. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class DetectColumnCountChangesAttribute : Attribute, IClassMapper + { + /// + /// A value indicating whether changes in the column + /// count should be detected. If true, a + /// will be thrown if a different column count is detected. + /// + public bool DetectColumnCountChanges { get; private set; } + + /// + /// A value indicating whether changes in the column + /// count should be detected. If true, a + /// will be thrown if a different column count is detected. + /// + public DetectColumnCountChangesAttribute(bool detectColumnCountChanges) + { + DetectColumnCountChanges = detectColumnCountChanges; + } + + /// + 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 +{ + /// + /// Detect the delimiter instead of using the delimiter from configuration. + /// Default is false. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class DetectDelimiterAttribute : Attribute, IClassMapper + { + /// + /// Detect the delimiter instead of using the delimiter from configuration. + /// + public bool DetectDelimiter { get; private set; } + + /// + /// Detect the delimiter instead of using the delimiter from configuration. + /// + public DetectDelimiterAttribute(bool detectDelimiter) + { + DetectDelimiter = detectDelimiter; + } + + /// + 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 +{ + /// + /// The possible delimiter values used when detecting the delimiter. + /// Default is [",", ";", "|", "\t"]. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class DetectDelimiterValuesAttribute : Attribute, IClassMapper + { + /// + /// The possible delimiter values used when detecting the delimiter. + /// + public string[] DetectDelimiterValues { get; private set; } + + /// + /// The possible delimiter values used when detecting the delimiter. + /// + /// Whitespace separated list of values. + public DetectDelimiterValuesAttribute(string detectDelimiterValues) + { + DetectDelimiterValues = Regex.Split(detectDelimiterValues, @"\s+"); + } + + /// + 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 +{ + /// + /// The encoding used when counting bytes. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class EncodingAttribute : Attribute, IClassMapper + { + /// + /// Gets the encoding used when counting bytes. + /// + public Encoding Encoding { get; private set; } + + /// + /// The encoding used when counting bytes. + /// + /// The encoding. + public EncodingAttribute(string encoding) + { + Encoding = Encoding.GetEncoding(encoding); + } + + /// + 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 +{ + /// + /// Ignore case when parsing enums. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class EnumIgnoreCaseAttribute : Attribute, IMemberMapper, IMemberReferenceMapper, IParameterMapper + { + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.EnumIgnoreCase = true; + } + + /// + public void ApplyTo(MemberReferenceMap referenceMap) + { + foreach (var memberMap in referenceMap.Data.Mapping.MemberMaps) + { + ApplyTo(memberMap); + } + } + + /// + 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 +{ + /// + /// The escape character used to escape a quote inside a field. + /// + [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )] + public class EscapeAttribute : Attribute, IClassMapper + { + /// + /// Gets the escape character used to escape a quote inside a field. + /// + public char Escape { get; private set; } + + /// + /// The escape character used to escape a quote inside a field. + /// + /// The escape character. + public EscapeAttribute( char escape ) + { + Escape = escape; + } + + /// + 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 +{ + /// + /// A value indicating if exception messages contain raw CSV data. + /// true if exception contain raw CSV data, otherwise false. + /// Default is true. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class ExceptionMessagesContainRawDataAttribute : Attribute, IClassMapper + { + /// + /// A value indicating if exception messages contain raw CSV data. + /// true if exception contain raw CSV data, otherwise false. + /// + public bool ExceptionMessagesContainRawData { get; private set; } + + /// + /// A value indicating if exception messages contain raw CSV data. + /// true if exception contain raw CSV data, otherwise false. + /// + /// + public ExceptionMessagesContainRawDataAttribute(bool exceptionMessagesContainRawData) + { + ExceptionMessagesContainRawData = exceptionMessagesContainRawData; + } + + /// + 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 +{ + /// + /// The string format to be used when type converting. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class FormatAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the formats. + /// + public string[] Formats { get; private set; } + + /// + /// The string format to be used when type converting. + /// + /// The format. + public FormatAttribute(string format) + { + Formats = new string[] { format }; + } + + /// + /// The string format to be used when type converting. + /// + /// The formats. + public FormatAttribute(params string[] formats) + { + Formats = formats; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.Formats = Formats; + } + + /// + 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 +{ + /// + /// A value indicating if the CSV file has a header record. + /// + [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )] + public class HasHeaderRecordAttribute : Attribute, IClassMapper + { + /// + /// Gets a value indicating if the CSV file has a header record. + /// + public bool HasHeaderRecord { get; private set; } + + /// + /// A value indicating if the CSV file has a header record. + /// + /// A value indicating if the CSV file has a header record. + public HasHeaderRecordAttribute( bool hasHeaderRecord ) + { + HasHeaderRecord = hasHeaderRecord; + } + + /// + 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 +{ + /// + /// Appends a prefix to the header of each field of the reference member. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class HeaderPrefixAttribute : Attribute, IMemberReferenceMapper, IParameterReferenceMapper + { + /// + /// Gets the prefix. + /// + public string? Prefix { get; private set; } + + /// + /// Gets a value indicating if the prefix should inherit parent prefixes. + /// + public bool Inherit { get; private set; } + + /// + /// Appends a prefix to the header of each field of the reference member. + /// + public HeaderPrefixAttribute() { } + + /// + /// Appends a prefix to the header of each field of the reference member. + /// + /// The prefix. + public HeaderPrefixAttribute(string prefix) + { + Prefix = prefix; + } + + /// + /// Appends a prefix to the header of each field of the reference member. + /// + /// Inherits parent object prefixes. + public HeaderPrefixAttribute(bool inherit) + { + Inherit = inherit; + } + + /// + /// Appends a prefix to the header of each field of the reference member. + /// + /// The prefix. + /// Inherits parent object prefixes. + public HeaderPrefixAttribute(string prefix, bool inherit) + { + Prefix = prefix; + Inherit = inherit; + } + + /// + public void ApplyTo(MemberReferenceMap referenceMap) + { + referenceMap.Data.Inherit = Inherit; + referenceMap.Data.Prefix = Prefix ?? referenceMap.Data.Member.Name + "."; + } + + /// + 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 +{ + /// + /// Defines methods to enable pluggable configuration. + /// + public interface IClassMapper + { + /// + /// Applies configuration. + /// + /// The configuration to apply to. + 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 +{ + /// + /// Defines methods to enable pluggable configuration of member mapping. + /// + public interface IMemberMapper + { + /// + /// Applies configuration to the given . + /// + /// The member map. + 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 +{ + /// + /// Defines methods to enable pluggable configuration of member reference mapping. + /// + public interface IMemberReferenceMapper + { + /// + /// Applies configuration to the given . + /// + /// The reference map. + 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 +{ + /// + /// Defines methods to enable pluggable configuration of parameter mapping. + /// + public interface IParameterMapper + { + /// + /// Applies configuration to the given . + /// + /// The parameter map. + 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 +{ + /// + /// Defines methods to enable pluggable configuration of parameter reference mapping. + /// + public interface IParameterReferenceMapper + { + /// + /// Applies configuration to the given . + /// + /// The reference map. + 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 +{ + /// + /// 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. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class IgnoreAttribute : Attribute, IMemberMapper, IMemberReferenceMapper, IParameterMapper + { + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.Ignore = true; + } + + /// + public void ApplyTo(MemberReferenceMap referenceMap) + { + foreach (var memberMap in referenceMap.Data.Mapping.MemberMaps) + { + ApplyTo(memberMap); + } + } + + /// + 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 +{ + /// + /// Ignores base classes when auto mapping. + /// + [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 +{ + /// + /// A value indicating if blank lines should be ignored when reading. + /// + [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )] + public class IgnoreBlankLinesAttribute : Attribute, IClassMapper + { + /// + /// Gets a value indicating if blank lines should be ignored when reading. + /// + public bool IgnoreBlankLines { get; private set; } + + /// + /// A value indicating if blank lines should be ignored when reading. + /// + /// The Ignore Blank Lines Flag. + public IgnoreBlankLinesAttribute( bool ignoreBlankLines ) + { + IgnoreBlankLines = ignoreBlankLines; + } + + /// + 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 +{ + /// + /// Gets a value indicating whether references + /// should be ignored when auto mapping. true to ignore + /// references, otherwise false. Default is false. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class IgnoreReferencesAttribute : Attribute, IClassMapper + { + /// + /// Gets a value indicating whether references + /// should be ignored when auto mapping. true to ignore + /// references, otherwise false. Default is false. + /// + public bool IgnoreReferences { get; private set; } + + /// + /// Gets a value indicating whether references + /// should be ignored when auto mapping. true to ignore + /// references, otherwise false. Default is false. + /// + /// Ignore references value. + public IgnoreReferencesAttribute(bool ignoreReferences) + { + IgnoreReferences = ignoreReferences; + } + + /// + 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 +{ + /// + /// A value indicating if private member should be read from and written to. + /// + [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )] + public class IncludePrivateMembersAttribute : Attribute, IClassMapper + { + /// + /// Gets a value indicating if private member should be read from and written to. + /// + public bool IncludePrivateMembers { get; private set; } + + /// + /// A value indicating if private member should be read from and written to. + /// + /// The Include Private Members Flag. + public IncludePrivateMembersAttribute( bool includePrivateMembers ) + { + IncludePrivateMembers = includePrivateMembers; + } + + /// + 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 +{ + /// + /// 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. + /// + [AttributeUsage( AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true )] + public class IndexAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the index. + /// + public int Index { get; private set; } + + /// + /// Gets the index end. + /// + public int IndexEnd { get; private set; } + + /// + /// 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. + /// + /// The index. + /// The index end. + public IndexAttribute( int index, int indexEnd = -1 ) + { + Index = index; + IndexEnd = indexEnd; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.Index = Index; + memberMap.Data.IndexEnd = IndexEnd; + memberMap.Data.IsIndexSet = true; + } + + /// + 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 +{ + /// + /// Gets the characters that are used for injection attacks. + /// + public class InjectionCharactersAttribute : Attribute, IClassMapper + { + /// + /// Gets the characters that are used for injection attacks. + /// Default is '=', '@', '+', '-', '\t', '\r'. + /// + public char[] InjectionCharacters { get; private set; } + + /// + /// Gets the characters that are used for injection attacks. + /// + /// + public InjectionCharactersAttribute(string injectionCharacters) + { + InjectionCharacters = Regex.Split(injectionCharacters, @"\s+").Select(s => s[0]).ToArray(); + } + + /// + 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 +{ + /// + /// The character used to escape a detected injection. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class InjectionEscapeCharacterAttribute : Attribute, IClassMapper + { + /// + /// The character used to escape a detected injection. + /// + public char InjectionEscapeCharacter { get; private set; } + + /// + /// The character used to escape a detected injection. + /// + /// + public InjectionEscapeCharacterAttribute(char injectionEscapeCharacter) + { + InjectionEscapeCharacter = injectionEscapeCharacter; + } + + /// + 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 +{ + /// + /// The injection options. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class InjectionOptionsAttribute : Attribute, IClassMapper + { + /// + /// The injection options. + /// + public InjectionOptions InjectionOptions { get; private set; } + + /// + /// The injection options. + /// + /// + public InjectionOptionsAttribute(InjectionOptions injectionOptions) + { + InjectionOptions = injectionOptions; + } + + /// + 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 +{ + /// + /// A value indicating if a line break found in a quote field should + /// be considered bad data. true to consider a line break bad data, otherwise false. + /// Defaults to false. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class LineBreakInQuotedFieldIsBadDataAttribute : Attribute, IClassMapper + { + /// + /// A value indicating if a line break found in a quote field should + /// be considered bad data. true to consider a line break bad data, otherwise false. + /// + public bool LineBreakInQuotedFieldIsBadData { get; private set; } + + /// + /// A value indicating if a line break found in a quote field should + /// be considered bad data. true to consider a line break bad data, otherwise false. + /// + /// + public LineBreakInQuotedFieldIsBadDataAttribute(bool lineBreakInQuotedFieldIsBadData) + { + LineBreakInQuotedFieldIsBadData = lineBreakInQuotedFieldIsBadData; + } + + /// + 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 +{ + /// + /// Gets or sets the maximum size of a field. + /// Defaults to 0, indicating maximum field size is not checked. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class MaxFieldSizeAttribute : Attribute, IClassMapper + { + /// + /// Gets or sets the maximum size of a field. + /// + public double MaxFieldSize { get; private set; } + + /// + /// Gets or sets the maximum size of a field. + /// + /// + public MaxFieldSizeAttribute(double maxFieldSize) + { + MaxFieldSize = maxFieldSize; + } + + /// + 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 +{ + /// + /// The member types that are used when auto mapping. + /// MemberTypes are flags, so you can choose more than one. + /// Default is Properties. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class MemberTypesAttribute : Attribute, IClassMapper + { + /// + /// The member types that are used when auto mapping. + /// MemberTypes are flags, so you can choose more than one. + /// Default is Properties. + /// + public MemberTypes MemberTypes { get; private set; } + + /// + /// The member types that are used when auto mapping. + /// MemberTypes are flags, so you can choose more than one. + /// Default is Properties. + /// + public MemberTypesAttribute(MemberTypes memberTypes) + { + MemberTypes = memberTypes; + } + + /// + 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 +{ + /// + /// The mode. + /// See for more details. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class ModeAttribute : Attribute, IClassMapper + { + /// + /// The mode. + /// See for more details. + /// + public CsvMode Mode { get; private set; } + + /// + /// The mode. + /// See for more details. + /// + /// + public ModeAttribute(CsvMode mode) + { + Mode = mode; + } + + /// + 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 +{ + /// + /// 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. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class NameAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the names. + /// + public string[] Names { get; private set; } + + /// + /// 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. + /// + /// The name + public NameAttribute(string name) + { + Names = new string[] { name }; + } + + /// + /// 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. + /// + /// The names. + public NameAttribute(params string[] names) + { + if (names == null || names.Length == 0) + { + throw new ArgumentNullException(nameof(names)); + } + + Names = names; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.Names.Clear(); + memberMap.Data.Names.AddRange(Names); + memberMap.Data.IsNameSet = true; + } + + /// + 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 +{ + /// + /// When reading, is used to get the + /// index of the name used when there + /// are multiple names that are the same. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class NameIndexAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// The name index. + /// + public int NameIndex { get; private set; } + + /// + /// When reading, is used to get the + /// index of the name used when there + /// are multiple names that are the same. + /// + /// The name index. + public NameIndexAttribute(int nameIndex) + { + NameIndex = nameIndex; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.NameIndex = NameIndex; + } + + /// + 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 +{ + /// + /// 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. + /// + [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; + } + + /// + 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 +{ + /// + /// The string values used to represent null when converting. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class NullValuesAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the null values. + /// + public string[] NullValues { get; private set; } + + /// + /// The string values used to represent null when converting. + /// + /// The null values. + public NullValuesAttribute(string nullValue) + { + NullValues = new string[] { nullValue }; + } + + /// + /// The string values used to represent null when converting. + /// + /// The null values. + public NullValuesAttribute(params string[] nullValues) + { + NullValues = nullValues; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.NullValues.Clear(); + memberMap.Data.TypeConverterOptions.NullValues.AddRange(NullValues); + } + + /// + 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 +{ + /// + /// The to use when type converting. + /// This is used when doing any number conversions. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class NumberStylesAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the number styles. + /// + public NumberStyles NumberStyles { get; private set; } + + /// + /// The to use when type converting. + /// This is used when doing any number conversions. + /// + /// The number styles. + public NumberStylesAttribute(NumberStyles numberStyles) + { + NumberStyles = numberStyles; + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverterOptions.NumberStyles = NumberStyles; + } + + /// + 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 +{ + /// + /// Ignore the member when reading if no matching field name can be found. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class OptionalAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.IsOptional = true; + } + + /// + 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 +{ + /// + /// The size of the buffer used when processing fields. + /// Default is 1024. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class ProcessFieldBufferSizeAttribute : Attribute, IClassMapper + { + /// + /// The size of the buffer used when processing fields. + /// + public int ProcessFieldBufferSize { get; private set; } + + /// + /// The size of the buffer used when processing fields. + /// + /// + public ProcessFieldBufferSizeAttribute(int processFieldBufferSize) + { + ProcessFieldBufferSize = processFieldBufferSize; + } + + /// + 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 +{ + /// + /// The character used to quote fields. + /// + [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )] + public class QuoteAttribute : Attribute, IClassMapper + { + /// + /// Gets the character used to quote fields. + /// + public char Quote { get; private set; } + + /// + /// The character used to quote fields. + /// + /// The quote character. + public QuoteAttribute( char quote ) + { + Quote = quote; + } + + /// + 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 +{ + /// + /// The fields trimming options. + /// + [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = true )] + public class TrimOptionsAttribute : Attribute, IClassMapper + { + /// + /// Gets the fields trimming options. + /// + public TrimOptions TrimOptions { get; private set; } + + /// + /// The fields trimming options. + /// + /// The TrimOptions. + public TrimOptionsAttribute( TrimOptions trimOptions ) + { + TrimOptions = trimOptions; + } + + /// + 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 +{ + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class TypeConverterAttribute : Attribute, IMemberMapper, IParameterMapper + { + /// + /// Gets the type converter. + /// + public ITypeConverter TypeConverter { get; private set; } + + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The type of the . + public TypeConverterAttribute(Type typeConverterType) : this(typeConverterType, new object[0]) { } + + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The type of the . + /// Type constructor arguments for the type converter. + 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)}"); + } + + /// + public void ApplyTo(MemberMap memberMap) + { + memberMap.Data.TypeConverter = TypeConverter; + } + + /// + 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 +{ + /// + /// 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. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class UseNewObjectForNullReferenceMembersAttribute : Attribute, IClassMapper + { + /// + /// 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. + /// + public bool UseNewObjectForNullReferenceMembers { get; private set; } + + /// + /// 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. + /// + /// The value. + public UseNewObjectForNullReferenceMembersAttribute(bool useNewObjectForNullReferenceMembers) + { + UseNewObjectForNullReferenceMembers = useNewObjectForNullReferenceMembers; + } + + /// + 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 +{ + /// + /// Characters considered whitespace. + /// Used when trimming fields. + /// Default is [' ']. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class WhiteSpaceCharsAttribute : Attribute, IClassMapper + { + /// + /// Characters considered whitespace. + /// Used when trimming fields. + /// + public char[] WhiteSpaceChars { get; private set; } + + /// + /// Characters considered whitespace. + /// Used when trimming fields. + /// + /// + public WhiteSpaceCharsAttribute(string whiteSpaceChars) + { + WhiteSpaceChars = Regex.Split(whiteSpaceChars, @"\s").Select(s => s[0]).ToArray(); + } + + /// + 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 +{ + /// + /// Maps class members to CSV fields. + /// + public abstract class ClassMap + { + private static readonly List enumerableConverters = new List + { + typeof(ArrayConverter), + typeof(CollectionGenericConverter), + typeof(EnumerableConverter), + typeof(IDictionaryConverter), + typeof(IDictionaryGenericConverter), + typeof(IEnumerableConverter), + typeof(IEnumerableGenericConverter) + }; + + /// + /// The type of the class this map is for. + /// + public virtual Type ClassType { get; private set; } + + /// + /// The class constructor parameter mappings. + /// + public virtual List ParameterMaps { get; } = new List(); + + /// + /// The class member mappings. + /// + public virtual MemberMapCollection MemberMaps { get; } = new MemberMapCollection(); + + /// + /// The class member reference mappings. + /// + public virtual MemberReferenceMapCollection ReferenceMaps { get; } = new MemberReferenceMapCollection(); + + /// + /// Allow only internal creation of CsvClassMap. + /// + /// The type of the class this map is for. + internal ClassMap(Type classType) + { + ClassType = classType; + } + + /// + /// Maps a member to a CSV field. + /// + /// 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. + /// The member to map. + /// If true, an existing map will be used if available. + /// If false, a new map is created for the same member. + /// The member mapping. + 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; + } + + /// + /// Maps a non-member to a CSV field. This allows for writing + /// data that isn't mapped to a class member. + /// + /// The member mapping. + public virtual MemberMap Map() + { + var memberMap = new MemberMap(null); + memberMap.Data.Index = GetMaxIndex() + 1; + MemberMaps.Add(memberMap); + + return memberMap; + } + + /// + /// Maps a member to another class map. + /// + /// The type of the class map. + /// The member. + /// Constructor arguments used to create the reference map. + /// The reference mapping for the member. + 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; + } + + /// + /// Maps a constructor parameter to a CSV field. + /// + /// The name of the constructor parameter. + 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); + } + + /// + /// Maps a constructor parameter to a CSV field. + /// + /// A function that returns the for the constructor. + /// The name of the constructor parameter. + public virtual ParameterMap Parameter(Func 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); + } + + /// + /// Maps a constructor parameter to a CSV field. + /// + /// The for the constructor. + /// The for the constructor parameter. + 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; + } + + /// + /// Auto maps all members for the given type. If a member + /// is mapped again it will override the existing map. + /// + /// The culture. + public virtual void AutoMap(CultureInfo culture) + { + AutoMap(new CsvConfiguration(culture)); + } + + /// + /// Auto maps all members for the given type. If a member + /// is mapped again it will override the existing map. + /// + /// The configuration. + public virtual void AutoMap(CsvConfiguration configuration) + { + AutoMap(new CsvContext(configuration)); + } + + /// + /// Auto maps all members for the given type. If a member + /// is mapped again it will override the existing map. + /// + /// The context. + 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(); + 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); + } + + /// + /// Get the largest index for the + /// members and references. + /// + /// The max index. + 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(); + 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(); + } + + /// + /// Resets the indexes based on the given start index. + /// + /// The index start. + /// The last index + 1. + 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; + } + + /// + /// Auto maps the given map and checks for circular references as it goes. + /// + /// The map to auto map. + /// The context. + /// The list of parents for the map. + /// The index starting point. + protected virtual void AutoMapMembers(ClassMap map, CsvContext context, LinkedList 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(); + 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(); + 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(); + 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() != 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); + } + + /// + /// Auto maps the given map using constructor parameters. + /// + /// The map. + /// The context. + /// The list of parents for the map. + /// The index starting point. + protected virtual void AutoMapConstructorParameters(ClassMap map, CsvContext context, LinkedList 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(true).Any() || parameter.GetCustomAttributes(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); + } + + /// + /// Checks for circular references. + /// + /// The type to check for. + /// The list of parents to check against. + /// A value indicating if a circular reference was found. + /// True if a circular reference was found, otherwise false. + protected virtual bool CheckForCircularReference(Type type, LinkedList 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; + } + + /// + /// Gets the generic type for this class map. + /// + protected virtual Type GetGenericType() + { + return GetType().GetTypeInfo().BaseType?.GetGenericArguments()[0] ?? throw new ConfigurationException(); + } + + /// + /// Applies attribute configurations to the map. + /// + /// The parameter map. + protected virtual void ApplyAttributes(ParameterMap parameterMap) + { + var parameter = parameterMap.Data.Parameter; + var attributes = parameter.GetCustomAttributes().OfType(); + + foreach (var attribute in attributes) + { + attribute.ApplyTo(parameterMap); + } + } + + /// + /// Applies attribute configurations to the map. + /// + /// The parameter reference map. + protected virtual void ApplyAttributes(ParameterReferenceMap referenceMap) + { + var parameter = referenceMap.Data.Parameter; + var attributes = parameter.GetCustomAttributes().OfType(); + + foreach (var attribute in attributes) + { + attribute.ApplyTo(referenceMap); + } + } + + /// + /// Applies attribute configurations to the map. + /// + /// The member map. + protected virtual void ApplyAttributes(MemberMap memberMap) + { + if (memberMap.Data.Member == null) + { + return; + } + + var member = memberMap.Data.Member; + var attributes = member.GetCustomAttributes().OfType(); + + foreach (var attribute in attributes) + { + attribute.ApplyTo(memberMap); + } + } + + /// + /// Applies attribute configurations to the map. + /// + /// The member reference map. + protected virtual void ApplyAttributes(MemberReferenceMap referenceMap) + { + var member = referenceMap.Data.Member; + var attributes = member.GetCustomAttributes().OfType(); + + 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 +{ + /// + /// Has mapping capabilities. + /// + /// The class type. + public interface IHasMap : IBuildableClass + { + /// + /// Maps a member to a CSV field. + /// + /// The member to map. + /// If true, an existing map will be used if available. + /// If false, a new map is created for the same member. + /// The member mapping. + IHasMapOptions Map(Expression> expression, bool useExistingMap = true); + } + + /// + /// Options after a mapping call. + /// + /// The class type. + /// The member type. + public interface IHasMapOptions : + IHasMap, + IHasTypeConverter, + IHasIndex, + IHasName, + IHasOptional, + IHasConvertUsing, + IHasDefault, + IHasConstant, + IHasValidate + { } + + /// + /// Has type converter capabilities. + /// + /// The class type. + /// The member type. + public interface IHasTypeConverter : IBuildableClass + { + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The TypeConverter to use. + IHasTypeConverterOptions TypeConverter(ITypeConverter typeConverter); + + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The of the + /// to use. + IHasTypeConverterOptions TypeConverter() where TConverter : ITypeConverter; + } + + /// + /// Options after a type converter call. + /// + /// The class type. + /// The member type. + public interface IHasTypeConverterOptions : + IHasMap, + IHasDefault, + IHasValidate + { } + + /// + /// Has index capabilities. + /// + /// The class type. + /// The member type. + public interface IHasIndex : IBuildableClass + { + /// + /// 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. + /// + /// The index of the CSV field. + /// The end index used when mapping to an member. + IHasIndexOptions Index(int index, int indexEnd = -1); + } + + /// + /// Options after an index call. + /// + /// The class type. + /// The member type. + public interface IHasIndexOptions : + IHasMap, + IHasTypeConverter, + IHasName, + IHasDefault, + IHasValidate + { } + + /// + /// Has optional capabilities. + /// + /// The class type. + /// The member type. + public interface IHasOptional : IBuildableClass + { + /// + /// Ignore the member when reading if no matching field name can be found. + /// + IHasOptionalOptions Optional(); + } + + /// + /// Options after an optional call. + /// + /// The class type. + /// The member type. + public interface IHasOptionalOptions : + IHasMap, + IHasTypeConverter, + IHasName, + IHasDefault, + IHasValidate + { } + + /// + /// Has name capabilities. + /// + /// The class type. + /// The member type. + public interface IHasName : IBuildableClass + { + /// + /// 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. + /// + /// The possible names of the CSV field. + IHasNameOptions Name(params string[] names); + } + + /// + /// Options after a name call. + /// + /// The class type. + /// The member type. + public interface IHasNameOptions : + IHasMap, + IHasTypeConverter, + IHasNameIndex, + IHasDefault, + IHasValidate + { } + + /// + /// Has name index capabilities. + /// + /// The class type. + /// The member type. + public interface IHasNameIndex : IBuildableClass + { + /// + /// When reading, is used to get the + /// index of the name used when there + /// are multiple names that are the same. + /// + /// The index of the name. + IHasNameIndexOptions NameIndex(int index); + } + + /// + /// Options after a name index call. + /// + /// The class type. + /// The member type. + public interface IHasNameIndexOptions : + IHasMap, + IHasTypeConverter, + IHasDefault, + IHasValidate + { } + + /// + /// Has convert using capabilities. + /// + /// The class type. + /// The member type. + public interface IHasConvertUsing : IBuildableClass + { + /// + /// Specifies an expression to be used to convert data in the + /// row to the member. + /// + /// The convert expression. + IHasMap ConvertUsing(ConvertFromString convertExpression); + + /// + /// Specifies an expression to be used to convert the object + /// to a field. + /// + /// The convert expression. + IHasMap ConvertUsing(ConvertToString convertExpression); + } + + /// + /// Has default capabilities. + /// + /// The class type. + /// The member type. + public interface IHasDefault : IBuildableClass + { + /// + /// The default value that will be used when reading when + /// the CSV field is empty. + /// + /// The default value. + IHasDefaultOptions Default(TMember defaultValue); + + /// + /// 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 to convert + /// the field. This could potentially have runtime errors. + /// + /// The default value. + IHasDefaultOptions Default(string defaultValue); + } + + /// + /// Options after a default call. + /// + /// The class type. + /// The member type. + public interface IHasDefaultOptions : + IHasMap, + IHasValidate + { } + + /// + /// Has constant capabilities. + /// + /// The class type. + /// The member type. + public interface IHasConstant : IBuildableClass + { + /// + /// 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. + /// + /// The constant value. + IHasMap Constant(TMember value); + } + + /// + /// Has validate capabilities. + /// + /// The class type. + /// The member type. + public interface IHasValidate : IBuildableClass + { + /// + /// 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 + /// will be thrown. + /// + /// The validation expression. + IHasMap Validate(Validate validateExpression); + } + + /// + /// Has build capabilities. + /// + /// The class type. + public interface IBuildableClass + { + /// + /// Builds the . + /// + ClassMap Build(); + } + + internal class ClassMapBuilder : IHasMap + { + private readonly ClassMap map; + + public ClassMapBuilder() + { + map = new BuilderClassMap(); + } + + public IHasMapOptions Map(Expression> expression, bool useExistingMap = true) + { + return new MemberMapBuilder(map, map.Map(expression, useExistingMap)); + } + + public ClassMap Build() + { + return map; + } + + private class BuilderClassMap : ClassMap { } + } + + internal class MemberMapBuilder : + IHasMap, + IHasMapOptions, + IHasTypeConverter, + IHasTypeConverterOptions, + IHasIndex, + IHasIndexOptions, + IHasName, + IHasNameOptions, + IHasNameIndex, + IHasNameIndexOptions, + IHasOptional, + IHasOptionalOptions, + IHasConvertUsing, + IHasDefault, + IHasDefaultOptions, + IHasConstant, + IHasValidate + { + private readonly ClassMap classMap; + private readonly MemberMap memberMap; + + public MemberMapBuilder(ClassMap classMap, MemberMap 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 Map(Expression> expression, bool useExistingMap = true) + { + return new MemberMapBuilder(classMap, classMap.Map(expression, useExistingMap)); + } +#pragma warning restore CS0693 // Type parameter has the same name as the type parameter from outer type + + public IHasMap ConvertUsing(ConvertFromString convertExpression) + { + memberMap.Convert(convertExpression); + return this; + } + + public IHasMap ConvertUsing(ConvertToString convertExpression) + { + memberMap.Convert(convertExpression); + return this; + } + + public IHasDefaultOptions Default(TMember defaultValue) + { + memberMap.Default(defaultValue); + return this; + } + + public IHasDefaultOptions Default(string defaultValue) + { + memberMap.Default(defaultValue); + return this; + } + + public IHasIndexOptions Index(int index, int indexEnd = -1) + { + memberMap.Index(index, indexEnd); + return this; + } + + public IHasNameOptions Name(params string[] names) + { + memberMap.Name(names); + return this; + } + + public IHasNameIndexOptions NameIndex(int index) + { + memberMap.NameIndex(index); + return this; + } + + public IHasOptionalOptions Optional() + { + memberMap.Optional(); + return this; + } + + public IHasTypeConverterOptions TypeConverter(ITypeConverter typeConverter) + { + memberMap.TypeConverter(typeConverter); + return this; + } + + public IHasTypeConverterOptions TypeConverter() where TConverter : ITypeConverter + { + memberMap.TypeConverter(); + return this; + } + + public IHasMap Constant(TMember value) + { + memberMap.Constant(value); + return this; + } + + public IHasMap Validate(Validate validateExpression) + { + memberMap.Validate(validateExpression); + return this; + } + + public ClassMap 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 +{ + /// + /// Collection that holds CsvClassMaps for record types. + /// + public class ClassMapCollection + { + private readonly Dictionary data = new Dictionary(); + private readonly CsvContext context; + + /// + /// Gets the for the specified record type. + /// + /// + /// The . + /// + /// The record type. + /// The for the specified record type. + 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; + } + } + } + } + + /// + /// Creates a new instance using the given configuration. + /// + /// The context. + public ClassMapCollection(CsvContext context) + { + this.context = context; + } + + /// + /// Finds the for the specified record type. + /// + /// The record type. + /// The for the specified record type. + public virtual ClassMap? Find() + { + return (ClassMap?)this[typeof(T)]; + } + + /// + /// Adds the specified map for it's record type. If a map + /// already exists for the record type, the specified + /// map will replace it. + /// + /// The map. + internal virtual void Add(ClassMap map) + { + SetMapDefaults(map); + + var type = GetGenericCsvClassMapType(map.GetType()).GetGenericArguments().First(); + + data[type] = map; + } + + /// + /// Removes the class map. + /// + /// The class map type. + 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); + } + + /// + /// Removes all maps. + /// + internal virtual void Clear() + { + data.Clear(); + } + + /// + /// Goes up the inheritance tree to find the type instance of CsvClassMap{}. + /// + /// The type to traverse. + /// The type that is CsvClassMap{}. + private Type GetGenericCsvClassMapType(Type type) + { + if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(ClassMap<>)) + { + return type; + } + + return GetGenericCsvClassMapType(type.GetTypeInfo().BaseType); + } + + /// + /// 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. + /// + /// The map to set defaults on. + 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 +{ + /// + /// Maps class members to CSV fields. + /// + /// The of class to map. + public abstract class ClassMap : ClassMap + { + /// + /// Creates an instance of . + /// + public ClassMap() : base(typeof(TClass)) { } + + /// + /// Maps a member to a CSV field. + /// + /// The member to map. + /// If true, an existing map will be used if available. + /// If false, a new map is created for the same member. + /// The member mapping. + public virtual MemberMap Map(Expression> expression, bool useExistingMap = true) + { + var (classMap, member) = GetMemberMap(expression); + var memberMap = classMap.Map(typeof(TClass), member, useExistingMap); ; + + return (MemberMap)memberMap; + } + + /// + /// Maps a member to a CSV field. + /// + /// The member to map. + /// If true, an existing map will be used if available. + /// If false, a new map is created for the same member. + /// The member mapping. + public virtual MemberMap Map(Expression> expression, bool useExistingMap = true) + { + var (classMap, member) = GetMemberMap(expression); + var memberMap = classMap.Map(typeof(TClass), member, useExistingMap); + + return memberMap; + } + + /// + /// 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. + /// + /// The type of the class map. + /// The expression. + /// Constructor arguments used to create the reference map. + /// The reference mapping for the member. + public virtual MemberReferenceMap References(Expression> expression, params object[] constructorArgs) where TClassMap : ClassMap + { + var member = ReflectionHelper.GetMember(expression); + return References(typeof(TClassMap), member, constructorArgs); + } + + private (ClassMap, MemberInfo) GetMemberMap(Expression> 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 +{ + /// + /// Represents configuration errors that occur. + /// + [Serializable] + public class ConfigurationException : CsvHelperException + { + /// + /// Initializes a new instance of the class. + /// + public ConfigurationException() { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The message that describes the error. + public ConfigurationException( string message ) : base( message ) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public 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 +{ + /// Holds the default callback methods for delegate members of CsvHelper.Configuration.Configuration. + public static class ConfigurationFunctions + { + private static readonly char[] lineEndingChars = new char[] { '\r', '\n' }; + + /// + /// Throws a if is not empty. + /// + 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()); + } + + /// + /// Throws a MissingFieldException. + /// + 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}"); + } + + /// + /// Throws a . + /// + 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."); + } + + /// + /// Throws the given . + /// + public static bool ReadingExceptionOccurred(ReadingExceptionOccurredArgs args) + { + return true; + } + + /// + /// Returns true if the field contains a , + /// starts with a space, ends with a space, contains \r or \n, or contains + /// the . + /// + /// The args. + /// true if the field should be quoted, otherwise false. + 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; + } + + /// + /// Returns the as given. + /// + public static string PrepareHeaderForMatch(PrepareHeaderForMatchArgs args) + { + return args.Header; + } + + /// + /// Returns true if : + /// 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. + /// + 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; + } + + /// + /// 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. + /// + public static ConstructorInfo GetConstructor(GetConstructorArgs args) + { + return args.ClassType.GetConstructorWithMostParameters(); + } + + /// + /// Returns the header name ran through . + /// If no header exists, property names will be Field1, Field2, Field3, etc. + /// + /// The args. + 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; + } + + /// + /// Detects the delimiter based on the given text. + /// Return the detected delimiter or null if one wasn't found. + /// + /// The args. + 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>(); + 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(); + 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 +{ + /// + /// Configuration used for reading and writing CSV data. + /// + public record CsvConfiguration : IReaderConfiguration, IWriterConfiguration + { + private string newLine = "\r\n"; + + /// + public virtual bool AllowComments { get; set; } + + /// + public virtual BadDataFound BadDataFound { get; set; } = ConfigurationFunctions.BadDataFound; + + /// + public virtual int BufferSize { get; set; } = 0x1000; + + /// + public virtual bool CacheFields { get; set; } + + /// + public virtual char Comment { get; set; } = '#'; + + /// + public virtual bool CountBytes { get; set; } + + /// + public virtual CultureInfo CultureInfo { get; protected set; } + + /// + public virtual string Delimiter { get; set; } + + /// + public virtual bool DetectDelimiter { get; set; } + + /// + public virtual GetDelimiter GetDelimiter { get; set; } = ConfigurationFunctions.GetDelimiter; + + /// + public virtual string[] DetectDelimiterValues { get; set; } = new[] { ",", ";", "|", "\t" }; + + /// + public virtual bool DetectColumnCountChanges { get; set; } + + /// + public virtual IComparer? DynamicPropertySort { get; set; } + + /// + public virtual Encoding Encoding { get; set; } = Encoding.UTF8; + + /// + public virtual char Escape { get; set; } = '"'; + + /// + public virtual bool ExceptionMessagesContainRawData { get; set; } = true; + + /// + public virtual GetConstructor GetConstructor { get; set; } = ConfigurationFunctions.GetConstructor; + + /// + public virtual GetDynamicPropertyName GetDynamicPropertyName { get; set; } = ConfigurationFunctions.GetDynamicPropertyName; + + /// + public virtual bool HasHeaderRecord { get; set; } = true; + + /// + public virtual HeaderValidated HeaderValidated { get; set; } = ConfigurationFunctions.HeaderValidated; + + /// + public virtual bool IgnoreBlankLines { get; set; } = true; + + /// + public virtual bool IgnoreReferences { get; set; } + + /// + public virtual bool IncludePrivateMembers { get; set; } + + /// + public virtual char[] InjectionCharacters { get; set; } = new[] { '=', '@', '+', '-', '\t', '\r' }; + + /// + public virtual char InjectionEscapeCharacter { get; set; } = '\''; + + /// + public virtual InjectionOptions InjectionOptions { get; set; } + + /// + public bool IsNewLineSet { get; private set; } + + /// + public virtual bool LineBreakInQuotedFieldIsBadData { get; set; } + + /// + public double MaxFieldSize { get; set; } + + /// + public virtual MemberTypes MemberTypes { get; set; } = MemberTypes.Properties; + + /// + public virtual MissingFieldFound MissingFieldFound { get; set; } = ConfigurationFunctions.MissingFieldFound; + + /// + public virtual CsvMode Mode { get; set; } + + /// + public virtual string NewLine + { + get => newLine; + set + { + IsNewLineSet = true; + newLine = value; + } + } + + /// + public virtual PrepareHeaderForMatch PrepareHeaderForMatch { get; set; } = ConfigurationFunctions.PrepareHeaderForMatch; + + /// + public virtual int ProcessFieldBufferSize { get; set; } = 1024; + + /// + public virtual char Quote { get; set; } = '"'; + + /// + public virtual ReadingExceptionOccurred ReadingExceptionOccurred { get; set; } = ConfigurationFunctions.ReadingExceptionOccurred; + + /// + public virtual ReferenceHeaderPrefix? ReferenceHeaderPrefix { get; set; } + + /// + public ShouldQuote ShouldQuote { get; set; } = ConfigurationFunctions.ShouldQuote; + + /// + public virtual ShouldSkipRecord? ShouldSkipRecord { get; set; } + + /// + public virtual ShouldUseConstructorParameters ShouldUseConstructorParameters { get; set; } = ConfigurationFunctions.ShouldUseConstructorParameters; + + /// + public virtual TrimOptions TrimOptions { get; set; } + + /// + public virtual bool UseNewObjectForNullReferenceMembers { get; set; } = true; + + /// + public virtual char[] WhiteSpaceChars { get; set; } = new char[] { ' ' }; + + /// + /// Initializes a new instance of the class + /// using the given . Since + /// uses for it's default, the given + /// will be used instead. + /// + /// The culture information. + /// The type that contains the configuration attributes. + /// This will call automatically. + public CsvConfiguration(CultureInfo cultureInfo, Type? attributesType = null) + { + CultureInfo = cultureInfo; + Delimiter = cultureInfo.TextInfo.ListSeparator; + + if (attributesType != null) + { + ApplyAttributes(attributesType); + } + } + + /// + /// Validates the configuration. + /// + public void Validate() + { + var escape = Escape.ToString(); + var quote = Quote.ToString(); + var lineEndings = new[] { "\r", "\n", "\r\n" }; + var whiteSpaceChars = WhiteSpaceChars.Select(c => c.ToString()).ToArray(); + + // Escape + if (escape == Delimiter) throw new ConfigurationException($"The escape character '{Escape}' and delimiter '{Delimiter}' cannot be the same."); + if (escape == NewLine && IsNewLineSet) throw new ConfigurationException($"The escape character '{Escape}' and new line '{NewLine}' cannot be the same."); + if (lineEndings.Contains(Escape.ToString()) && !IsNewLineSet) throw new ConfigurationException($"The escape character '{Escape}' cannot be a line ending. ('\\r', '\\n', '\\r\\n')"); + if (whiteSpaceChars.Contains(escape)) throw new ConfigurationException($"The escape character '{Escape}' cannot be a WhiteSpaceChar."); + + // Quote + if (quote == Delimiter) throw new ConfigurationException($"The quote character '{Quote}' and the delimiter '{Delimiter}' cannot be the same."); + if (quote == NewLine && IsNewLineSet) throw new ConfigurationException($"The quote character '{Quote}' and new line '{NewLine}' cannot be the same."); + if (lineEndings.Contains(quote)) throw new ConfigurationException($"The quote character '{Quote}' cannot be a line ending. ('\\r', '\\n', '\\r\\n')"); + if (whiteSpaceChars.Contains(quote)) throw new ConfigurationException($"The quote character '{Quote}' cannot be a WhiteSpaceChar."); + + // Delimiter + if (Delimiter == NewLine && IsNewLineSet) throw new ConfigurationException($"The delimiter '{Delimiter}' and new line '{NewLine}' cannot be the same."); + if (lineEndings.Contains(Delimiter)) throw new ConfigurationException($"The delimiter '{Delimiter}' cannot be a line ending. ('\\r', '\\n', '\\r\\n')"); + if (whiteSpaceChars.Contains(Delimiter)) throw new ConfigurationException($"The delimiter '{Delimiter}' cannot be a WhiteSpaceChar."); + + // Detect Delimiter + if (DetectDelimiter && DetectDelimiterValues.Length == 0) throw new ConfigurationException($"At least one value is required for {nameof(DetectDelimiterValues)} when {nameof(DetectDelimiter)} is enabled."); + } + + /// + /// Applies class level attribute to configuration. + /// + /// Type with attributes. + public CsvConfiguration ApplyAttributes() + { + return ApplyAttributes(typeof(T)); + } + + /// + /// Applies class level attribute to configuration. + /// + /// Type with attributes. + public CsvConfiguration ApplyAttributes(Type type) + { + var attributes = type.GetCustomAttributes().OfType(); + foreach (var attribute in attributes) + { + attribute.ApplyTo(this); + } + + return this; + } + } +} 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 +{ + /// + /// A default that can be used + /// to create a class map dynamically. + /// + /// + public class DefaultClassMap : ClassMap + { + } +} 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 +{ + /// + /// Configuration used for the . + /// + public interface IParserConfiguration + { + /// + /// Gets the culture info used to read an write CSV files. + /// + CultureInfo CultureInfo { get; } + + /// + /// Cache fields that are created when parsing. + /// Default is false. + /// + bool CacheFields { get; } + + /// + /// The newline string to use. Default is \r\n (CRLF). + /// When writing, this value is always used. + /// When reading, this value is only used if explicitly set. + /// If not set, the parser uses one of \r\n, \r, or \n. + /// + string NewLine { get; } + + /// + /// A value indicating if was set. + /// + /// + /// true if was set. false if is the default. + /// + bool IsNewLineSet { get; } + + /// + /// The mode. + /// See for more details. + /// + CsvMode Mode { get; } + + /// + /// Gets the size of the buffer + /// used for parsing and writing CSV files. + /// Default is 0x1000. + /// + int BufferSize { get; } + + /// + /// The size of the buffer used when processing fields. + /// Default is 1024. + /// + int ProcessFieldBufferSize { get; } + + /// + /// Gets a value indicating whether the number of bytes should + /// be counted while parsing. Default is false. This will slow down parsing + /// because it needs to get the byte count of every char for the given encoding. + /// The needs to be set correctly for this to be accurate. + /// + bool CountBytes { get; } + + /// + /// Gets the encoding used when counting bytes. + /// + Encoding Encoding { get; } + + /// + /// Gets the function that is called when bad field data is found. A field + /// has bad data if it contains a quote and the field is not quoted (escaped). + /// You can supply your own function to do other things like logging the issue + /// instead of throwing an exception. + /// + BadDataFound BadDataFound { get; } + + /// + /// Gets or sets the maximum size of a field. + /// Defaults to 0, indicating maximum field size is not checked. + /// + double MaxFieldSize { get; } + + /// + /// Gets a value indicating if a line break found in a quote field should + /// be considered bad data. true to consider a line break bad data, otherwise false. + /// Defaults to false. + /// + bool LineBreakInQuotedFieldIsBadData { get; } + + /// + /// Gets the character used to denote + /// a line that is commented out. Default is '#'. + /// + char Comment { get; } + + /// + /// Gets a value indicating if comments are allowed. + /// true to allow commented out lines, otherwise false. + /// + bool AllowComments { get; } + + /// + /// Gets a value indicating if blank lines + /// should be ignored when reading. + /// true to ignore, otherwise false. Default is true. + /// + bool IgnoreBlankLines { get; } + + /// + /// Gets the character used to quote fields. + /// Default is '"'. + /// + char Quote { get; } + + /// + /// The delimiter used to separate fields. + /// Default is . + /// + string Delimiter { get; } + + /// + /// Detect the delimiter instead of using the delimiter from configuration. + /// Default is false. + /// + bool DetectDelimiter { get; } + + /// + /// Gets the function that is called when is enabled. + /// + GetDelimiter GetDelimiter { get; } + + /// + /// The possible delimiter values used when detecting the delimiter. + /// Default is [",", ";", "|", "\t"]. + /// + string[] DetectDelimiterValues { get; } + + /// + /// The character used to escape characters. + /// Default is '"'. + /// + char Escape { get; } + + /// + /// Gets the field trimming options. + /// + TrimOptions TrimOptions { get; } + + /// + /// Characters considered whitespace. + /// Used when trimming fields. + /// Default is [' ']. + /// + char[] WhiteSpaceChars { get; } + + /// + /// A value indicating if exception messages contain raw CSV data. + /// true if exception contain raw CSV data, otherwise false. + /// Default is true. + /// + bool ExceptionMessagesContainRawData { get; } + + /// + /// Validates the configuration. + /// + void Validate(); + } +} diff --git a/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 +{ + /// + /// Configuration used for the . + /// + public interface IReaderConfiguration : IParserConfiguration + { + /// + /// Gets a value indicating if the + /// CSV file has a header record. + /// Default is true. + /// + bool HasHeaderRecord { get; } + + /// + /// Gets the function that is called when a header validation check is ran. The default function + /// will throw a if there is no header for a given member mapping. + /// You can supply your own function to do other things like logging the issue instead of throwing an exception. + /// + HeaderValidated HeaderValidated { get; } + + /// + /// Gets the function that is called when a missing field is found. The default function will + /// throw a . You can supply your own function to do other things + /// like logging the issue instead of throwing an exception. + /// + MissingFieldFound MissingFieldFound { get; } + + /// + /// Gets the function that is called when a reading exception occurs. + /// The default function will re-throw the given exception. If you want to ignore + /// reading exceptions, you can supply your own function to do other things like + /// logging the issue. + /// + ReadingExceptionOccurred ReadingExceptionOccurred { get; } + + /// + /// Prepares the header field for matching against a member name. + /// The header field and the member name are both ran through this function. + /// You should do things like trimming, removing whitespace, removing underscores, + /// and making casing changes to ignore case. + /// + PrepareHeaderForMatch PrepareHeaderForMatch { get; } + + /// + /// Determines if constructor parameters should be used to create + /// the class instead of the default constructor and members. + /// + ShouldUseConstructorParameters ShouldUseConstructorParameters { get; } + + /// + /// Chooses the constructor to use for constructor mapping. + /// + GetConstructor GetConstructor { get; } + + /// + /// Gets the name to use for the property of the dynamic object. + /// + GetDynamicPropertyName GetDynamicPropertyName { get; } + + /// + /// Gets a value indicating whether references + /// should be ignored when auto mapping. true to ignore + /// references, otherwise false. Default is false. + /// + bool IgnoreReferences { get; } + + /// + /// Gets the callback that will be called to + /// determine whether to skip the given record or not. + /// + ShouldSkipRecord? ShouldSkipRecord { get; } + + /// + /// Gets a value indicating if private + /// member should be read from and written to. + /// true to include private member, otherwise false. Default is false. + /// + bool IncludePrivateMembers { get; } + + /// + /// Gets a callback that will return the prefix for a reference header. + /// + ReferenceHeaderPrefix ReferenceHeaderPrefix { get; } + + /// + /// Gets a value indicating whether changes in the column + /// count should be detected. If true, a + /// will be thrown if a different column count is detected. + /// + bool DetectColumnCountChanges { get; } + + /// + /// Gets the member types that are used when auto mapping. + /// MemberTypes are flags, so you can choose more than one. + /// Default is Properties. + /// + MemberTypes MemberTypes { get; } + } +} diff --git a/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 +{ + /// + /// Configuration used for the . + /// + public interface IWriterConfiguration + { + /// + /// Gets the size of the buffer + /// used for parsing and writing CSV files. + /// Default is 0x1000. + /// + int BufferSize { get; } + + /// + /// The mode. + /// See for more details. + /// + CsvMode Mode { get; } + + /// + /// Gets the delimiter used to separate fields. + /// Default is ','; + /// + string Delimiter { get; } + + /// + /// Gets the character used to quote fields. + /// Default is '"'. + /// + char Quote { get; } + + /// + /// The character used to escape characters. + /// Default is '"'. + /// + char Escape { get; } + + /// + /// Gets the field trimming options. + /// + TrimOptions TrimOptions { get; } + + /// + /// Gets the injection options. + /// + InjectionOptions InjectionOptions { get; } + + /// + /// Gets the characters that are used for injection attacks. + /// + char[] InjectionCharacters { get; } + + /// + /// Gets the character used to escape a detected injection. + /// + char InjectionEscapeCharacter { get; } + + /// + /// The newline string to use. Default is \r\n (CRLF). + /// When writing, this value is always used. + /// When reading, this value is only used if explicitly set. If not set, + /// the parser uses one of \r\n, \r, or \n. + /// + string NewLine { get; } + + /// + /// A value indicating if was set. + /// + /// + /// true if was set. false if is the default. + /// + bool IsNewLineSet { get; } + + /// + /// Gets a function that is used to determine if a field should get quoted + /// when writing. + /// + ShouldQuote ShouldQuote { get; } + + /// + /// Gets the culture info used to read and write CSV files. + /// + CultureInfo CultureInfo { get; } + + /// + /// Gets a value indicating if comments are allowed. + /// True to allow commented out lines, otherwise false. + /// + bool AllowComments { get; } + + /// + /// Gets the character used to denote + /// a line that is commented out. Default is '#'. + /// + char Comment { get; } + + /// + /// Gets a value indicating if the + /// CSV file has a header record. + /// Default is true. + /// + bool HasHeaderRecord { get; } + + /// + /// Gets a value indicating whether references + /// should be ignored when auto mapping. True to ignore + /// references, otherwise false. Default is false. + /// + bool IgnoreReferences { get; } + + /// + /// Gets a value indicating if private + /// member should be read from and written to. + /// True to include private member, otherwise false. Default is false. + /// + bool IncludePrivateMembers { get; } + + /// + /// Gets a callback that will return the prefix for a reference header. + /// + ReferenceHeaderPrefix ReferenceHeaderPrefix { get; } + + /// + /// Gets the member types that are used when auto mapping. + /// MemberTypes are flags, so you can choose more than one. + /// Default is Properties. + /// + MemberTypes MemberTypes { get; } + + /// + /// Gets a value indicating that during writing if a new + /// object should be created when a reference member is null. + /// True to create a new object and use it's defaults for the + /// fields, or false to leave the fields empty for all the + /// reference member's member. + /// + bool UseNewObjectForNullReferenceMembers { get; } + + /// + /// Gets the comparer used to order the properties + /// of dynamic objects when writing. The default is null, + /// which will preserve the order the object properties + /// were created with. + /// + IComparer DynamicPropertySort { get; } + + /// + /// A value indicating if exception messages contain raw CSV data. + /// true if exception contain raw CSV data, otherwise false. + /// Default is true. + /// + bool ExceptionMessagesContainRawData { get; } + + /// + /// Validates the configuration. + /// + void Validate(); + } +} diff --git a/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 +{ + /// + /// Options for handling injection attacks. + /// + public enum InjectionOptions + { + /// + /// No injection protection. + /// + None = 0, + /// + /// Escape injection characters. + /// + Escape, + /// + /// Strip injection characters. + /// + Strip, + /// + /// Throw an exception if injection characters are detected. + /// + 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 +{ + /// + /// Mapping info for a member to a CSV field. + /// + [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 + { + /// + /// Gets the member map data. + /// + public virtual MemberMapData Data { get; protected set; } + + /// + /// Type converter options. + /// + public virtual MemberMapTypeConverterOption TypeConverterOption { get; protected set; } + + /// + /// Creates an instance of using the given Type and . + /// + /// Type of the class the member being mapped belongs to. + /// The member being mapped. + 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; + } + + /// + /// 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. + /// + /// The possible names of the CSV field. + 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; + } + + /// + /// When reading, is used to get the + /// index of the name used when there + /// are multiple names that are the same. + /// + /// The index of the name. + public virtual MemberMap NameIndex(int index) + { + Data.NameIndex = index; + + return this; + } + + /// + /// 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. + /// + /// The index of the CSV field. + /// The end index used when mapping to an member. + public virtual MemberMap Index(int index, int indexEnd = -1) + { + Data.Index = index; + Data.IsIndexSet = true; + Data.IndexEnd = indexEnd; + + return this; + } + + /// + /// 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. + /// + public virtual MemberMap Ignore() + { + Data.Ignore = true; + + return this; + } + + /// + /// 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. + /// + /// True to ignore, otherwise false. + public virtual MemberMap Ignore(bool ignore) + { + Data.Ignore = ignore; + + return this; + } + + /// + /// The default value that will be used when reading when + /// the CSV field is empty. + /// + /// The default value. + /// Use default on conversion failure. + 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; + } + + /// + /// 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. + /// + /// The constant value. + 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; + } + + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The TypeConverter to use. + public virtual MemberMap TypeConverter(ITypeConverter typeConverter) + { + Data.TypeConverter = typeConverter; + + return this; + } + + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The of the + /// to use. + public virtual MemberMap TypeConverter() where TConverter : ITypeConverter + { + TypeConverter(ObjectResolver.Current.Resolve()); + + return this; + } + + /// + /// Ignore the member when reading if no matching field name can be found. + /// + public virtual MemberMap Optional() + { + Data.IsOptional = true; + + return this; + } + + /// + /// Specifies an expression to be used to validate a field when reading. + /// + /// + public virtual MemberMap Validate(Validate validateExpression) + { + return Validate(validateExpression, args => $"Field '{args.Field}' is not valid."); + } + + /// + /// Specifies an expression to be used to validate a field when reading along with specified exception message. + /// + /// + /// + 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(validateCallExpression, fieldParameter); + Data.ValidateMessageExpression = Expression.Lambda(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 +{ + /// + /// A collection that holds 's. + /// + [DebuggerDisplay("Count = {list.Count}")] + public class MemberMapCollection : IList + { + private readonly List list = new List(); + private readonly IComparer comparer; + + /// + /// Gets the number of elements contained in the . + /// + /// + /// The number of elements contained in the . + /// + public virtual int Count => list.Count; + + /// + /// Gets a value indicating whether the is read-only. + /// + /// + /// true if the is read-only; otherwise, false. + /// + public virtual bool IsReadOnly => false; + + /// + /// Initializes a new instance of the class. + /// + public MemberMapCollection() : this(new MemberMapComparer()) { } + + /// + /// Initializes a new instance of the class. + /// + /// The comparer to use when sorting the member maps. + public MemberMapCollection(IComparer comparer) + { + this.comparer = comparer; + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A that can be used to iterate through the collection. + /// + /// 1 + public virtual IEnumerator GetEnumerator() + { + return list.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + /// 2 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Adds an item to the . + /// + /// The object to add to the . + /// The is read-only. + /// + public virtual void Add(MemberMap item) + { + list.Add(item); + list.Sort(comparer); + } + + /// + /// Adds a range of items to the . + /// + /// The collection to add. + public virtual void AddRange(ICollection collection) + { + list.AddRange(collection); + list.Sort(comparer); + } + + /// + /// Removes all items from the . + /// + /// The is read-only. + /// + public virtual void Clear() + { + list.Clear(); + } + + /// + /// Determines whether the contains a specific value. + /// + /// + /// true if is found in the ; otherwise, false. + /// + /// The object to locate in the . + /// + public virtual bool Contains(MemberMap item) + { + return list.Contains(item); + } + + /// + /// Copies the elements of the to an , starting at a particular index. + /// + /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.The zero-based index in at which copying begins. is null. is less than 0.The number of elements in the source is greater than the available space from to the end of the destination . + public virtual void CopyTo(MemberMap[] array, int arrayIndex) + { + list.CopyTo(array, arrayIndex); + } + + /// + /// Removes the first occurrence of a specific object from the . + /// + /// + /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . + /// + /// The object to remove from the . + /// The is read-only. + /// + public virtual bool Remove(MemberMap item) + { + return list.Remove(item); + } + + /// + /// Determines the index of a specific item in the . + /// + /// + /// The index of if found in the list; otherwise, -1. + /// + /// The object to locate in the . + /// + public virtual int IndexOf(MemberMap item) + { + return list.IndexOf(item); + } + + /// + /// Inserts an item to the at the specified index. + /// + /// The zero-based index at which should be inserted. + /// The object to insert into the . + /// is not a valid index in the . + /// The is read-only. + /// + public virtual void Insert(int index, MemberMap item) + { + list.Insert(index, item); + } + + /// + /// Removes the item at the specified index. + /// + /// The zero-based index of the item to remove. + /// is not a valid index in the . + /// The is read-only. + /// + public virtual void RemoveAt(int index) + { + list.RemoveAt(index); + } + + /// + /// Gets or sets the element at the specified index. + /// + /// + /// The element at the specified index. + /// + /// The zero-based index of the element to get or set. + /// is not a valid index in the . + /// The member is set and the is read-only. + /// + public virtual MemberMap this[int index] + { + get { return list[index]; } + set { list[index] = value; } + } + + /// + /// Finds the using the given member expression. + /// + /// The the member is on. + /// The member expression. + /// The for the given expression, or null if not found. + public virtual MemberMap? Find(Expression> expression) + { + var member = ReflectionHelper.GetMember(expression); + return Find(member); + } + + /// + /// Finds the using the given member. + /// + /// The member. + /// The for the given expression, or null if not found. + 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; + } + + /// + /// Adds the members from the mapping. This will recursively + /// traverse the mapping tree and add all members for + /// reference maps. + /// + /// The mapping where the members are added from. + 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 +{ + /// + /// Used to compare s. + /// The order is by field index ascending. Any + /// fields that don't have an index are pushed + /// to the bottom. + /// + internal class MemberMapComparer : IComparer + { + /// + /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. + /// + /// + /// Value + /// Condition + /// Less than zero + /// is less than . + /// Zero + /// equals . + /// Greater than zero + /// is greater than . + /// + /// The first object to compare. + /// The second object to compare. + /// Neither nor implements the interface. + /// -or- + /// and are of different types and neither one can handle comparisons with the other. + /// 2 + public virtual int Compare( object x, object y ) + { + var xMember = x as MemberMap; + var yMember = y as MemberMap; + return Compare( xMember, yMember ); + } + + /// + /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. + /// + /// + /// Value + /// Condition + /// Less than zero + /// is less than . + /// Zero + /// equals . + /// Greater than zero + /// is greater than . + /// + /// The first object to compare. + /// The second object to compare. + /// + 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 +{ + /// + /// The configured data for the member map. + /// + public class MemberMapData + { + /// + /// Gets the member type. + /// + 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); + } + } + + /// + /// Gets the that the data + /// is associated with. + /// + public virtual MemberInfo? Member { get; private set; } + + /// + /// Gets the list of column names. + /// + public virtual MemberNameCollection Names { get; } = new MemberNameCollection(); + + /// + /// Gets or sets the index of the name. + /// This is used if there are multiple + /// columns with the same names. + /// + public virtual int NameIndex { get; set; } + + /// + /// Gets or sets a value indicating if the name was + /// explicitly set. True if it was explicitly set, + /// otherwise false. + /// + public virtual bool IsNameSet { get; set; } + + /// + /// Gets or sets the column index. + /// + public virtual int Index { get; set; } = -1; + + /// + /// 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. + /// + public virtual int IndexEnd { get; set; } = -1; + + /// + /// Gets or sets a value indicating if the index was + /// explicitly set. True if it was explicitly set, + /// otherwise false. + /// + public virtual bool IsIndexSet { get; set; } + + /// + /// Gets or sets the type converter. + /// + public virtual ITypeConverter? TypeConverter { get; set; } + + /// + /// Gets or sets the type converter options. + /// + public virtual TypeConverterOptions TypeConverterOptions { get; set; } = new TypeConverterOptions(); + + /// + /// Gets or sets a value indicating whether the field should be ignored. + /// + public virtual bool Ignore { get; set; } + + /// + /// Gets or sets the default value used when a CSV field is empty. + /// + public virtual object? Default { get; set; } + + /// + /// 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. + /// + public virtual bool IsDefaultSet { get; set; } + + /// + /// Gets or setse a value indicating if the default value should be used when + /// a type conversion failure happens. true to use the default, otherwise + /// false. + /// + public virtual bool UseDefaultOnConversionFailure { get; set; } + + /// + /// Gets or sets the constant value used for every record. + /// + public virtual object? Constant { get; set; } + + /// + /// Gets or sets a value indicating if a constant was explicitly set. + /// + public virtual bool IsConstantSet { get; set; } + + /// + /// Gets or sets the expression used to convert data in the + /// row to the member. + /// + public virtual Expression ReadingConvertExpression { get; set; } + + /// + /// Gets or sets the expression to be used to convert the object + /// to a field. + /// + public virtual Expression WritingConvertExpression { get; set; } + + /// + /// Gets or sets the expression use to validate a field. + /// + public virtual Expression ValidateExpression { get; set; } + + /// + /// Gets or sets the expression used to get the validation message when validation fails. + /// + public virtual Expression ValidateMessageExpression { get; set; } + + /// + /// Gets or sets a value indicating if a field is optional. + /// + public virtual bool IsOptional { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The member. + 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 +{ + /// + /// Sets type converter options on a member map. + /// + public class MemberMapTypeConverterOption + { + private readonly MemberMap memberMap; + + /// + /// Creates a new instance using the given . + /// + /// The member map the options are being applied to. + public MemberMapTypeConverterOption(MemberMap memberMap) + { + this.memberMap = memberMap; + } + + /// + /// The used when type converting. + /// This will override the global + /// setting. + /// + /// The culture info. + public virtual MemberMap CultureInfo(CultureInfo cultureInfo) + { + memberMap.Data.TypeConverterOptions.CultureInfo = cultureInfo; + + return memberMap; + } + + /// + /// The to use when type converting. + /// This is used when doing any conversions. + /// + /// The date time style. + public virtual MemberMap DateTimeStyles(DateTimeStyles dateTimeStyle) + { + memberMap.Data.TypeConverterOptions.DateTimeStyle = dateTimeStyle; + + return memberMap; + } + + /// + /// The to use when type converting. + /// This is used when doing converting. + /// + /// The time span styles. + public virtual MemberMap TimespanStyles(TimeSpanStyles timeSpanStyles) + { + memberMap.Data.TypeConverterOptions.TimeSpanStyle = timeSpanStyles; + + return memberMap; + } + + /// + /// The to use when type converting. + /// This is used when doing any number conversions. + /// + /// + public virtual MemberMap NumberStyles(NumberStyles numberStyle) + { + memberMap.Data.TypeConverterOptions.NumberStyles = numberStyle; + + return memberMap; + } + + /// + /// The string format to be used when type converting. + /// + /// The format. + public virtual MemberMap Format(params string[] formats) + { + memberMap.Data.TypeConverterOptions.Formats = formats; + + return memberMap; + } + + /// + /// The to use when converting. + /// This is used when doing conversions. + /// + /// Kind of the URI. + public virtual MemberMap UriKind(UriKind uriKind) + { + memberMap.Data.TypeConverterOptions.UriKind = uriKind; + + return memberMap; + } + + /// + /// The string values used to represent a boolean when converting. + /// + /// A value indicating whether true values or false values are being set. + /// A value indication if the current values should be cleared before adding the new ones. + /// The string boolean values. + 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; + } + + /// + /// The string values used to represent null when converting. + /// + /// The values that represent null. + /// + public virtual MemberMap NullValues(params string[] nullValues) + { + return NullValues(true, nullValues); + } + + /// + /// The string values used to represent null when converting. + /// + /// A value indication if the current values should be cleared before adding the new ones. + /// The values that represent null. + /// + public virtual MemberMap NullValues(bool clearValues, params string[] nullValues) + { + if (clearValues) + { + memberMap.Data.TypeConverterOptions.NullValues.Clear(); + } + + memberMap.Data.TypeConverterOptions.NullValues.AddRange(nullValues); + + return memberMap; + } + + /// + /// Ignore case when parsing enums. + /// + /// true to ignore case, otherwise false. + 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 +{ + /// + /// Mapping info for a member to a CSV field. + /// + public class MemberMap : MemberMap + { + /// + /// Creates a new instance using the specified member. + /// + public MemberMap(MemberInfo? member) + { + TypeConverterOption = new MemberMapTypeConverterOption(this); + + Data = new MemberMapData(member); + } + + /// + /// 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. + /// + /// The possible names of the CSV field. + public new 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; + } + + /// + /// When reading, is used to get the + /// index of the name used when there + /// are multiple names that are the same. + /// + /// The index of the name. + public new virtual MemberMap NameIndex(int index) + { + Data.NameIndex = index; + + return this; + } + + /// + /// 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. + /// + /// The index of the CSV field. + /// The end index used when mapping to an member. + public new virtual MemberMap Index(int index, int indexEnd = -1) + { + Data.Index = index; + Data.IsIndexSet = true; + Data.IndexEnd = indexEnd; + + return this; + } + + /// + /// 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. + /// + public new virtual MemberMap Ignore() + { + Data.Ignore = true; + + return this; + } + + /// + /// 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. + /// + /// True to ignore, otherwise false. + public new virtual MemberMap Ignore(bool ignore) + { + Data.Ignore = ignore; + + return this; + } + + /// + /// The default value that will be used when reading when + /// the CSV field is empty. + /// + /// The default value. + /// Use default on conversion failure. + public virtual MemberMap Default(TMember defaultValue, bool useOnConversionFailure = false) + { + Data.Default = defaultValue; + Data.IsDefaultSet = true; + Data.UseDefaultOnConversionFailure = useOnConversionFailure; + + return this; + } + + /// + /// 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 to convert + /// the field. This could potentially have runtime errors. + /// + /// The default value. + /// Use default on conversion failure. + public virtual MemberMap Default(string defaultValue, bool useOnConversionFailure = false) + { + Data.Default = defaultValue; + Data.IsDefaultSet = true; + Data.UseDefaultOnConversionFailure = useOnConversionFailure; + + return this; + } + + /// + /// 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. + /// + /// The constant value. + public virtual MemberMap Constant(TMember? constantValue) + { + Data.Constant = constantValue; + Data.IsConstantSet = true; + + return this; + } + + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The TypeConverter to use. + public new virtual MemberMap TypeConverter(ITypeConverter typeConverter) + { + Data.TypeConverter = typeConverter; + + return this; + } + + /// + /// Specifies the to use + /// when converting the member to and from a CSV field. + /// + /// The of the + /// to use. + public new virtual MemberMap TypeConverter() where TConverter : ITypeConverter + { + TypeConverter(ObjectResolver.Current.Resolve()); + + return this; + } + + /// + /// Specifies an expression to be used to convert data in the + /// row to the member. + /// + /// The convert expression. + public virtual MemberMap Convert(ConvertFromString 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>(methodExpression, fieldParameter); + + Data.ReadingConvertExpression = lambdaExpression; + + return this; + } + + /// + /// Specifies an expression to be used to convert the object + /// to a field. + /// + /// The convert expression. + public virtual MemberMap Convert(ConvertToString convertToStringFunction) + { + var instance = convertToStringFunction.Target != null ? Expression.Constant(convertToStringFunction.Target) : null; + var fieldParameter = Expression.Parameter(typeof(ConvertToStringArgs), "args"); + var methodExpression = Expression.Call + ( + instance, + convertToStringFunction.Method, + fieldParameter + ); + var lambdaExpression = Expression.Lambda>(methodExpression, fieldParameter); + + Data.WritingConvertExpression = lambdaExpression; + + return this; + } + + /// + /// Ignore the member when reading if no matching field name can be found. + /// + public new virtual MemberMap Optional() + { + Data.IsOptional = true; + + return this; + } + + /// + /// Specifies an expression to be used to validate a field when reading. + /// + /// + public new virtual MemberMap Validate(Validate validateExpression) + { + return Validate(validateExpression, args => $"Field '{args.Field}' is not valid."); + } + + /// + /// Specifies an expression to be used to validate a field when reading along with specified exception message. + /// + /// + /// + public new virtual MemberMap 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(validateCallExpression, fieldParameter); + Data.ValidateMessageExpression = Expression.Lambda(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 +{ + /// + /// A collection that holds member names. + /// + public class MemberNameCollection : IEnumerable + { + private readonly List names = new List(); + + /// + /// Gets the name at the given index. If a prefix is set, + /// it will be prepended to the name. + /// + /// + /// + public string this[int index] + { + get { return Prefix + names[index]; } + set { names[index] = value; } + } + + /// + /// Gets the prefix to use for each name. + /// + public string Prefix { get; set; } + + /// + /// Gets the raw list of names without + /// the prefix being prepended. + /// + public List Names => names; + + /// + /// Gets the count. + /// + public int Count => names.Count; + + /// + /// Adds the given name to the collection. + /// + /// The name to add. + public void Add(string name) + { + names.Add(name); + } + + /// + /// Clears all names from the collection. + /// + public void Clear() + { + names.Clear(); + } + + /// + /// Adds a range of names to the collection. + /// + /// The range to add. + public void AddRange(IEnumerable names) + { + this.names.AddRange(names); + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A that can be used to iterate through the collection. + /// + /// 1 + public IEnumerator GetEnumerator() + { + for (var i = 0; i < names.Count; i++) + { + yield return this[i]; + } + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + /// 2 + 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 +{ + /// + /// Mapping info for a reference member mapping to a class. + /// + [DebuggerDisplay("Member = {Data.Member}, Prefix = {Data.Prefix}")] + public class MemberReferenceMap + { + private readonly MemberReferenceMapData data; + + /// + /// Gets the member reference map data. + /// + public MemberReferenceMapData Data => data; + + /// + /// Initializes a new instance of the class. + /// + /// The member. + /// The to use for the reference map. + public MemberReferenceMap(MemberInfo member, ClassMap mapping) + { + if (mapping == null) + { + throw new ArgumentNullException(nameof(mapping)); + } + + data = new MemberReferenceMapData(member, mapping); + } + + /// + /// Appends a prefix to the header of each field of the reference member. + /// + /// The prefix to be prepended to headers of each reference member. + /// Inherit parent prefixes. + /// The current + 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; + } + + /// + /// Get the largest index for the + /// members and references. + /// + /// The max index. + 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 +{ + /// + /// A collection that holds 's. + /// + [DebuggerDisplay("Count = {list.Count}")] + public class MemberReferenceMapCollection : IList + { + private readonly List list = new List(); + + /// Gets the number of elements contained in the . + /// The number of elements contained in the . + public virtual int Count => list.Count; + + /// Gets a value indicating whether the is read-only. + /// true if the is read-only; otherwise, false. + public virtual bool IsReadOnly => false; + + /// Gets or sets the element at the specified index. + /// The element at the specified index. + /// The zero-based index of the element to get or set. + /// + /// is not a valid index in the . + /// The member is set and the is read-only. + public virtual MemberReferenceMap this[int index] + { + get => list[index]; + set => list[index] = value; + } + + /// Returns an enumerator that iterates through the collection. + /// A that can be used to iterate through the collection. + /// 1 + public virtual IEnumerator GetEnumerator() + { + return list.GetEnumerator(); + } + + /// Returns an enumerator that iterates through a collection. + /// An object that can be used to iterate through the collection. + /// 2 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// Adds an item to the . + /// The object to add to the . + /// The is read-only. + public virtual void Add(MemberReferenceMap item) + { + list.Add(item); + } + + /// Removes all items from the . + /// The is read-only. + public virtual void Clear() + { + list.Clear(); + } + + /// Determines whether the contains a specific value. + /// true if is found in the ; otherwise, false. + /// The object to locate in the . + public virtual bool Contains(MemberReferenceMap item) + { + return list.Contains(item); + } + + /// Copies the elements of the to an , starting at a particular index. + /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. + /// The zero-based index in at which copying begins. + /// + /// is null. + /// + /// is less than 0. + /// The number of elements in the source is greater than the available space from to the end of the destination . + public virtual void CopyTo(MemberReferenceMap[] array, int arrayIndex) + { + list.CopyTo(array, arrayIndex); + } + + /// Removes the first occurrence of a specific object from the . + /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . + /// The object to remove from the . + /// The is read-only. + public virtual bool Remove(MemberReferenceMap item) + { + return list.Remove(item); + } + + /// Determines the index of a specific item in the . + /// The index of if found in the list; otherwise, -1. + /// The object to locate in the . + public virtual int IndexOf(MemberReferenceMap item) + { + return list.IndexOf(item); + } + + /// Inserts an item to the at the specified index. + /// The zero-based index at which should be inserted. + /// The object to insert into the . + /// + /// is not a valid index in the . + /// The is read-only. + public virtual void Insert(int index, MemberReferenceMap item) + { + list.Insert(index, item); + } + + /// Removes the item at the specified index. + /// The zero-based index of the item to remove. + /// + /// is not a valid index in the . + /// The is read-only. + public virtual void RemoveAt(int index) + { + list.RemoveAt(index); + } + + /// + /// Finds the using the given member expression. + /// + /// The the member is on. + /// The member expression. + /// The for the given expression, or null if not found. + public virtual MemberReferenceMap? Find(Expression> expression) + { + var member = ReflectionHelper.GetMember(expression); + return Find(member); + } + + /// + /// Finds the using the given member. + /// + /// The member. + /// The for the given expression, or null if not found. + 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 +{ + /// + /// The configuration data for the reference map. + /// + public class MemberReferenceMapData + { + private string prefix; + + /// + /// Gets or sets the header prefix to use. + /// + 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); + } + } + } + } + + /// + /// Gets or sets a value indicating if a prefix should inherit its parent. + /// true to inherit, otherwise false. + /// + public virtual bool Inherit { get; set; } + + /// + /// Gets the that the data + /// is associated with. + /// + public virtual MemberInfo Member { get; private set; } + + /// + /// Gets the mapping this is a reference for. + /// + public ClassMap Mapping { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The member. + /// The mapping this is a reference for. + 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 +{ + /// + /// Flags for the type of members that + /// can be used for auto mapping. + /// + [Flags] + public enum MemberTypes + { + /// + /// No members. This is not a valid value + /// and will cause an exception if used. + /// + None = 0, + + /// + /// Properties on a class. + /// + Properties = 1, + + /// + /// Fields on a class. + /// + 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 +{ + /// + /// 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. + /// + [DebuggerDisplay("Data = {Data}")] + public class ParameterMap + { + /// + /// Gets the parameter map data. + /// + public virtual ParameterMapData Data { get; protected set; } + + /// + /// Type converter options. + /// + public virtual ParameterMapTypeConverterOption TypeConverterOption { get; protected set; } + + /// + /// Gets or sets the map for a constructor type. + /// + public virtual ClassMap ConstructorTypeMap { get; set; } + + /// + /// Gets or sets the map for a reference type. + /// + public virtual ParameterReferenceMap ReferenceMap { get; set; } + + /// + /// Creates an instance of using + /// the given information. + /// + /// The parameter being mapped. + public ParameterMap(ParameterInfo parameter) + { + TypeConverterOption = new ParameterMapTypeConverterOption(this); + + Data = new ParameterMapData(parameter); + } + + /// + /// 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. + /// + /// The possible names of the CSV field. + 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; + } + + /// + /// When reading, is used to get the + /// index of the name used when there + /// are multiple names that are the same. + /// + /// The index of the name. + public virtual ParameterMap NameIndex(int index) + { + Data.NameIndex = index; + + return this; + } + + /// + /// 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. + /// + /// The index of the CSV field. + public virtual ParameterMap Index(int index) + { + Data.Index = index; + Data.IsIndexSet = true; + + return this; + } + + /// + /// Ignore the parameter when reading and writing. + /// + public virtual ParameterMap Ignore() + { + Data.Ignore = true; + + return this; + } + + /// + /// Ignore the parameter when reading and writing. + /// + /// True to ignore, otherwise false. + public virtual ParameterMap Ignore(bool ignore) + { + Data.Ignore = ignore; + + return this; + } + + /// + /// The default value that will be used when reading when + /// the CSV field is empty. + /// + /// The default value. + 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; + } + + /// + /// 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. + /// + /// The constant value. + 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; + } + + /// + /// The field is optional. + /// + public virtual ParameterMap Optional() + { + Data.IsOptional = true; + + return this; + } + + /// + /// Specifies the to use + /// when converting the parameter to and from a CSV field. + /// + /// The TypeConverter to use. + public virtual ParameterMap TypeConverter(ITypeConverter typeConverter) + { + Data.TypeConverter = typeConverter; + + return this; + } + + /// + /// Specifies the to use + /// when converting the parameter to and from a CSV field. + /// + /// The of the + /// to use. + public virtual ParameterMap TypeConverter() where TConverter : ITypeConverter + { + TypeConverter(ObjectResolver.Current.Resolve()); + + 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 +{ + /// + /// The constructor parameter data for the map. + /// + [DebuggerDisplay("Index = {Index}, Names = {string.Join(\", \", Names)}, Parameter = {Parameter}")] + public class ParameterMapData + { + /// + /// Gets the that the data + /// is associated with. + /// + public virtual ParameterInfo Parameter { get; private set; } + + /// + /// Gets the list of column names. + /// + public virtual MemberNameCollection Names { get; } = new MemberNameCollection(); + + /// + /// Gets or sets the index of the name. + /// This is used if there are multiple + /// columns with the same names. + /// + public virtual int NameIndex { get; set; } + + /// + /// Gets or sets a value indicating if the name was + /// explicitly set. True if it was explicitly set, + /// otherwise false. + /// + public virtual bool IsNameSet { get; set; } + + /// + /// Gets or sets the column index. + /// + public virtual int Index { get; set; } = -1; + + /// + /// Gets or sets a value indicating if the index was + /// explicitly set. True if it was explicitly set, + /// otherwise false. + /// + public virtual bool IsIndexSet { get; set; } + + /// + /// Gets or sets the type converter. + /// + public virtual ITypeConverter TypeConverter { get; set; } + + /// + /// Gets or sets the type converter options. + /// + public virtual TypeConverterOptions TypeConverterOptions { get; set; } = new TypeConverterOptions(); + + /// + /// Gets or sets a value indicating whether the field should be ignored. + /// + public virtual bool Ignore { get; set; } + + /// + /// Gets or sets the default value used when a CSV field is empty. + /// + public virtual object? Default { get; set; } + + /// + /// 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. + /// + public virtual bool IsDefaultSet { get; set; } + + /// + /// Gets or sets the constant value used for every record. + /// + public virtual object? Constant { get; set; } + + /// + /// Gets or sets a value indicating if a constant was explicitly set. + /// + public virtual bool IsConstantSet { get; set; } + + /// + /// Gets or sets a value indicating if a field is optional. + /// + public virtual bool IsOptional { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The constructor parameter. + 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 +{ + /// + /// Sets type converter options on a parameter map. + /// + public class ParameterMapTypeConverterOption + { + private readonly ParameterMap parameterMap; + + /// + /// Creates a new instance using the given . + /// + /// The member map the options are being applied to. + public ParameterMapTypeConverterOption(ParameterMap parameterMap) + { + this.parameterMap = parameterMap; + } + + /// + /// The used when type converting. + /// This will override the global + /// setting. + /// + /// The culture info. + public virtual ParameterMap CultureInfo(CultureInfo cultureInfo) + { + parameterMap.Data.TypeConverterOptions.CultureInfo = cultureInfo; + + return parameterMap; + } + + /// + /// The to use when type converting. + /// This is used when doing any conversions. + /// + /// The date time style. + public virtual ParameterMap DateTimeStyles(DateTimeStyles dateTimeStyle) + { + parameterMap.Data.TypeConverterOptions.DateTimeStyle = dateTimeStyle; + + return parameterMap; + } + + /// + /// The to use when type converting. + /// This is used when doing converting. + /// + /// The time span styles. + public virtual ParameterMap TimespanStyles(TimeSpanStyles timeSpanStyles) + { + parameterMap.Data.TypeConverterOptions.TimeSpanStyle = timeSpanStyles; + + return parameterMap; + } + + /// + /// The to use when type converting. + /// This is used when doing any number conversions. + /// + /// + public virtual ParameterMap NumberStyles(NumberStyles numberStyle) + { + parameterMap.Data.TypeConverterOptions.NumberStyles = numberStyle; + + return parameterMap; + } + + /// + /// The string format to be used when type converting. + /// + /// The format. + public virtual ParameterMap Format(params string[] formats) + { + parameterMap.Data.TypeConverterOptions.Formats = formats; + + return parameterMap; + } + + /// + /// The to use when converting. + /// This is used when doing conversions. + /// + /// Kind of the URI. + public virtual ParameterMap UriKind(UriKind uriKind) + { + parameterMap.Data.TypeConverterOptions.UriKind = uriKind; + + return parameterMap; + } + + /// + /// The string values used to represent a boolean when converting. + /// + /// A value indicating whether true values or false values are being set. + /// A value indication if the current values should be cleared before adding the new ones. + /// The string boolean values. + 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; + } + + /// + /// The string values used to represent null when converting. + /// + /// The values that represent null. + /// + public virtual ParameterMap NullValues(params string[] nullValues) + { + return NullValues(true, nullValues); + } + + /// + /// The string values used to represent null when converting. + /// + /// A value indication if the current values should be cleared before adding the new ones. + /// The values that represent null. + /// + 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 +{ + /// + /// Mapping info for a reference parameter mapping to a class. + /// + public class ParameterReferenceMap + { + private readonly ParameterReferenceMapData data; + + /// + /// Gets the parameter reference map data. + /// + public ParameterReferenceMapData Data => data; + + /// + /// Initializes a new instance of the class. + /// + /// The parameter. + /// The to use for the reference map. + public ParameterReferenceMap(ParameterInfo parameter, ClassMap mapping) + { + if (mapping == null) + { + throw new ArgumentNullException(nameof(mapping)); + } + + data = new ParameterReferenceMapData(parameter, mapping); + } + + /// + /// Appends a prefix to the header of each field of the reference parameter. + /// + /// The prefix to be prepended to headers of each reference parameter. + /// Inherit parent prefixes. + /// The current + 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; + } + + /// + /// Get the largest index for the + /// members and references. + /// + /// The max index. + 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 +{ + /// + /// The configuration data for the reference map. + /// + [DebuggerDisplay( "Prefix = {Prefix}, Parameter = {Parameter}" )] + public class ParameterReferenceMapData + { + private string prefix; + + /// + /// Gets or sets the header prefix to use. + /// + 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); + } + } + } + } + + /// + /// Gets or sets a value indicating if a prefix should inherit its parent. + /// true to inherit, otherwise false. + /// + public virtual bool Inherit { get; set; } + + /// + /// Gets the that the data + /// is associated with. + /// + public virtual ParameterInfo Parameter { get; private set; } + + /// + /// Gets the mapping this is a reference for. + /// + public ClassMap Mapping { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The parameter. + /// The mapping this is a reference for. + 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 +{ + /// + /// Options for trimming of fields. + /// + [Flags] + public enum TrimOptions + { + /// + /// No trimming. + /// + None = 0, + + /// + /// Trims the whitespace around a field. + /// + Trim = 1, + + /// + /// Trims the whitespace inside of quotes around a field. + /// + 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 +{ + /// + /// Share state for CsvHelper. + /// + public class CsvContext + { + /// + /// Gets or sets the . + /// + public virtual TypeConverterOptionsCache TypeConverterOptionsCache { get; set; } = new TypeConverterOptionsCache(); + + /// + /// Gets or sets the . + /// + public virtual TypeConverterCache TypeConverterCache { get; set; } = new TypeConverterCache(); + + /// + /// The configured s. + /// + public virtual ClassMapCollection Maps { get; private set; } + + /// + /// Gets the parser. + /// + public IParser Parser { get; private set; } + + /// + /// Gets the reader. + /// + public IReader Reader { get; internal set; } + + /// + /// Gets the writer. + /// + public IWriter Writer { get; internal set; } + + /// + /// Gets the configuration. + /// + public CsvConfiguration Configuration { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The reader. + 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); + } + + /// + /// Initializes a new instance of the class. + /// + /// The parser. + 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); + } + + /// + /// Initializes a new instance of the class. + /// + /// The writer. + 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); + } + + /// + /// Initializes a new instance of the class. + /// + /// The configuration. + public CsvContext(CsvConfiguration configuration) + { + Configuration = configuration; + Maps = new ClassMapCollection(this); + } + + /// + /// Use a to configure mappings. + /// When using a class map, no members are mapped by default. + /// Only member specified in the mapping are used. + /// + /// The type of mapping class to use. + public virtual TMap RegisterClassMap() where TMap : ClassMap + { + var map = ObjectResolver.Current.Resolve(); + RegisterClassMap(map); + + return map; + } + + /// + /// Use a to configure mappings. + /// When using a class map, no members are mapped by default. + /// Only members specified in the mapping are used. + /// + /// The type of mapping class to use. + 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; + } + + /// + /// Registers the class map. + /// + /// The class map to register. + 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); + } + + /// + /// Unregisters the class map. + /// + /// The map type to unregister. + public virtual void UnregisterClassMap() + where TMap : ClassMap + { + UnregisterClassMap(typeof(TMap)); + } + + /// + /// Unregisters the class map. + /// + /// The map type to unregister. + public virtual void UnregisterClassMap(Type classMapType) + { + Maps.Remove(classMapType); + } + + /// + /// Unregisters all class maps. + /// + public virtual void UnregisterClassMap() + { + Maps.Clear(); + } + + /// + /// Generates a for the type. + /// + /// The type to generate the map for. + /// The generate map. + public virtual ClassMap AutoMap() + { + var map = ObjectResolver.Current.Resolve>(); + map.AutoMap(this); + Maps.Add(map); + + return map; + } + + /// + /// Generates a for the type. + /// + /// The type to generate for the map. + /// The generate map. + 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 +{ + /// + /// Provides a means of reading a CSV file forward-only by using CsvReader. + /// + /// + public class CsvDataReader : IDataReader + { + private readonly CsvReader csv; + private readonly DataTable schemaTable; + private bool skipNextRead; + + /// + public object this[int i] + { + get + { + return csv[i] ?? string.Empty; + } + } + + /// + public object this[string name] + { + get + { + return csv[name] ?? string.Empty; + } + } + + /// + public int Depth + { + get + { + return 0; + } + } + + /// + public bool IsClosed { get; private set; } + + /// + public int RecordsAffected + { + get + { + return 0; + } + } + + /// + public int FieldCount + { + get + { + return csv?.Parser.Count ?? 0; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The CSV. + /// The DataTable representing the file schema. + 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(); + } + + /// + public void Close() + { + Dispose(); + } + + /// + public void Dispose() + { + csv.Dispose(); + IsClosed = true; + } + + /// + public bool GetBoolean(int i) + { + return csv.GetField(i); + } + + /// + public byte GetByte(int i) + { + return csv.GetField(i); + } + + /// + public long GetBytes(int i, long fieldOffset, byte[]? buffer, int bufferoffset, int length) + { + var bytes = csv.GetField(i); + + buffer ??= new byte[bytes.Length]; + + Array.Copy(bytes, fieldOffset, buffer, bufferoffset, length); + + return bytes.Length; + } + + /// + public char GetChar(int i) + { + return csv.GetField(i); + } + + /// + 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; + } + + /// + public IDataReader GetData(int i) + { + throw new NotSupportedException(); + } + + /// + 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; + } + + /// + public DateTime GetDateTime(int i) + { + return csv.GetField(i); + } + + /// + public decimal GetDecimal(int i) + { + return csv.GetField(i); + } + + /// + public double GetDouble(int i) + { + return csv.GetField(i); + } + + /// + public Type GetFieldType(int i) + { + return typeof(string); + } + + /// + public float GetFloat(int i) + { + return csv.GetField(i); + } + + /// + public Guid GetGuid(int i) + { + return csv.GetField(i); + } + + /// + public short GetInt16(int i) + { + return csv.GetField(i); + } + + /// + public int GetInt32(int i) + { + return csv.GetField(i); + } + + /// + public long GetInt64(int i) + { + return csv.GetField(i); + } + + /// + public string GetName(int i) + { + return csv.Configuration.HasHeaderRecord + ? csv.HeaderRecord[i] + : string.Empty; + } + + /// + 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."); + } + + /// + 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; + } + + /// + public string GetString(int i) + { + return csv.GetField(i) ?? string.Empty; + } + + /// + public object GetValue(int i) + { + return IsDBNull(i) ? DBNull.Value : (csv.GetField(i) ?? string.Empty); + } + + /// + 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; + } + + /// + public bool IsDBNull(int i) + { + var field = csv.GetField(i); + var nullValues = csv.Context.TypeConverterOptionsCache.GetOptions().NullValues; + + return field == null || nullValues.Contains(field); + } + + /// + public bool NextResult() + { + return false; + } + + /// + 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 @@ + + + + CsvHelper + A library for reading and writing CSV files. Extremely fast, flexible, and easy to use. Supports reading and writing of custom class objects. + Copyright © 2009-2022 Josh Close + Josh Close + + + CsvHelper + net6.0;netstandard2.1;netstandard2.0;net47;net462 + + latest + CsvHelper + en-US + true + true + + + + true + CsvHelper.snk + true + + + CsvHelper + csv;csvhelper;comma;separated;value;delimited + Icon.png + https://raw.github.com/JoshClose/CsvHelper/master/logo/Comma-Small.png + https://joshclose.github.io/CsvHelper/ + https://joshclose.github.io/CsvHelper/change-log + MS-PL OR Apache-2.0 + true + true + https://github.com/JoshClose/CsvHelper + git + true + snupkg + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + \ 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 @@ + + + True + + \ 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 @@ + + + True + + \ 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 @@ + + + True + + \ 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 @@ + + + True + + \ 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 @@ + + + True + + \ 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 @@ + + + True + + \ 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 @@ + + + True + + \ 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 @@ + + + True + + \ 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 Binary files /dev/null and b/ThirdParty/CsvHelper-master/src/CsvHelper/CsvHelper.snk 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 +{ + /// + /// Represents errors that occur in CsvHelper. + /// + [Serializable] + public class CsvHelperException : Exception + { + [NonSerialized] + private readonly CsvContext context; + + /// + /// Gets the context. + /// + public CsvContext Context => context; + + /// + /// Initializes a new instance of the CsvHelperException class. + /// + internal protected CsvHelperException() : base() { } + + /// + /// Initializes a new instance of the CsvHelperException class. + /// + /// The message that describes the error. + internal protected CsvHelperException(string message) : base(message) { } + + /// + /// Initializes a new instance of the CsvHelperException class. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + internal protected CsvHelperException(string message, Exception innerException) : base(message, innerException) { } + + /// + /// Initializes a new instance of the class. + /// + public CsvHelperException(CsvContext context) + { + this.context = context; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The context. + /// The message that describes the error. + public CsvHelperException(CsvContext context, string message) : base(AddDetails(message, context)) + { + this.context = context; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public CsvHelperException(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 +{ + /// + /// Mode to use when parsing and writing. + /// + public enum CsvMode + { + /// + /// Uses RFC 4180 format (default). + /// If a field contains a or , + /// it is wrapped in s. + /// If quoted field contains a , it is preceded by . + /// + RFC4180 = 0, + + /// + /// Uses escapes. + /// If a field contains a , , + /// or , it is preceded by . + /// Newline defaults to \n. + /// + Escape, + + /// + /// Doesn't use quotes or escapes. + /// This will ignore quoting and escape characters. This means a field cannot contain a + /// , , or + /// , as they cannot be escaped. + /// + 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 +{ + /// + /// Parses a CSV file. + /// + 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; + + /// + public long CharCount => charCount; + + /// + public long ByteCount => byteCount; + + /// + public int Row => row; + + /// + 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; + } + } + + /// + public string RawRecord => new string(buffer, rowStartPosition, bufferPosition - rowStartPosition); + + /// + public int Count => fieldsPosition; + + /// + public int RawRow => rawRow; + + /// + public string Delimiter => delimiter; + + /// + public CsvContext Context { get; private set; } + + /// + public IParserConfiguration Configuration => configuration; + + /// + 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; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The reader. + /// The culture. + /// if set to true [leave open]. + public CsvParser(TextReader reader, CultureInfo culture, bool leaveOpen = false) : this(reader, new CsvConfiguration(culture), leaveOpen) { } + + /// + /// Initializes a new instance of the class. + /// + /// The reader. + /// The configuration. + /// if set to true [leave open]. + 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]; + } + + /// + 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; + } + } + } + + /// + public async Task 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 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; + } + + /// + /// Processes a field that complies with RFC4180. + /// + /// The start index of the field. + /// The length of the field. + /// The number of counted quotes. + /// The processed field. + 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); + } + + /// + /// Processes a field that does not comply with RFC4180. + /// + /// The start index of the field. + /// The length of the field. + /// The processed field. + 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); + } + + /// + /// Processes an escaped field. + /// + /// The start index of the field. + /// The length of the field. + /// The processed field. + 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); + } + + /// + /// + /// Processes an non-escaped field. + /// + /// The start index of the field. + /// The length of the field. + /// The processed field. + 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); + } + + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes the object. + /// + /// Indicates if the object is being disposed. + 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; + } + + /// + /// Processes a raw field based on configuration. + /// This will remove quotes, remove escapes, and trim if configured to. + /// + [DebuggerDisplay("Start = {Start}, Length = {Length}, Buffer.Length = {Buffer.Length}")] + protected readonly struct ProcessedField + { + /// + /// The start of the field in the buffer. + /// + public readonly int Start; + + /// + /// The length of the field in the buffer. + /// + public readonly int Length; + + /// + /// The buffer that contains the field. + /// + public readonly char[] Buffer; + + /// + /// Creates a new instance of ProcessedField. + /// + /// The start of the field in the buffer. + /// The length of the field in the buffer. + /// The buffer that contains the field. + 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 + { + /// + /// Starting position of the field. + /// This is an offset from . + /// + 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 +{ + /// + /// Reads data that was parsed from . + /// + public class CsvReader : IReader + { + private readonly Lazy recordManager; + private readonly bool detectColumnCountChanges; + private readonly Dictionary> namedIndexes = new Dictionary>(); + private readonly Dictionary namedIndexCache = new Dictionary(); + private readonly Dictionary typeConverterOptionsCache = new Dictionary(); + 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; + + /// + public virtual int ColumnCount => columnCount; + + /// + public virtual int CurrentIndex => currentIndex; + + /// + public virtual string[]? HeaderRecord => headerRecord; + + /// + public virtual CsvContext Context => context; + + /// + public virtual IReaderConfiguration Configuration { get; private set; } + + /// + public virtual IParser Parser => parser; + + /// + /// Creates a new CSV reader using the given . + /// + /// The reader. + /// The culture. + /// true to leave the open after the object is disposed, otherwise false. + public CsvReader(TextReader reader, CultureInfo culture, bool leaveOpen = false) : this(new CsvParser(reader, culture, leaveOpen)) { } + + /// + /// Creates a new CSV reader using the given and + /// and as the default parser. + /// + /// The reader. + /// The configuration. + /// true to leave the open after the object is disposed, otherwise false. + public CsvReader(TextReader reader, IReaderConfiguration configuration, bool leaveOpen = false) : this(new CsvParser(reader, configuration, leaveOpen)) { } + + /// + /// Creates a new CSV reader using the given . + /// + /// The used to parse the CSV file. + 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(() => ObjectResolver.Current.Resolve(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; + } + + /// + public virtual bool ReadHeader() + { + if (!hasHeaderRecord) + { + throw new ReaderException(context, "Configuration.HasHeaderRecord is false."); + } + + headerRecord = parser.Record; + ParseNamedIndexes(); + + return headerRecord != null; + } + + /// + /// Validates the header to be of the given type. + /// + /// The expected type of the header + public virtual void ValidateHeader() + { + ValidateHeader(typeof(T)); + } + + /// + /// Validates the header to be of the given type. + /// + /// The expected type of the header. + 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(); + ValidateHeader(map, invalidHeaders); + + var args = new HeaderValidatedArgs(invalidHeaders.ToArray(), context); + headerValidated?.Invoke(args); + } + + /// + /// Validates the header to be of the given type. + /// + /// The mapped classes. + /// The invalid headers. + protected virtual void ValidateHeader(ClassMap map, List 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); + } + } + + /// + 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; + } + + /// + public virtual async Task 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; + } + + /// + public virtual string? this[int index] + { + get + { + CheckHasBeenRead(); + + return GetField(index); + } + } + + /// + public virtual string? this[string name] + { + get + { + CheckHasBeenRead(); + + return GetField(name); + } + } + + /// + public virtual string? this[string name, int index] + { + get + { + CheckHasBeenRead(); + + return GetField(name, index); + } + } + + /// + 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; + } + + /// + public virtual string? GetField(string name) + { + CheckHasBeenRead(); + + var index = GetFieldIndex(name); + if (index < 0) + { + return null; + } + + return GetField(index); + } + + /// + public virtual string? GetField(string name, int index) + { + CheckHasBeenRead(); + + var fieldIndex = GetFieldIndex(name, index); + if (fieldIndex < 0) + { + return null; + } + + return GetField(fieldIndex); + } + + /// + public virtual object? GetField(Type type, int index) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(type); + return GetField(type, index, converter); + } + + /// + public virtual object? GetField(Type type, string name) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(type); + return GetField(type, name, converter); + } + + /// + public virtual object? GetField(Type type, string name, int index) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(type); + return GetField(type, name, index, converter); + } + + /// + 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); + } + + /// + public virtual object? GetField(Type type, string name, ITypeConverter converter) + { + CheckHasBeenRead(); + + var index = GetFieldIndex(name); + return GetField(type, index, converter); + } + + /// + public virtual object? GetField(Type type, string name, int index, ITypeConverter converter) + { + CheckHasBeenRead(); + + var fieldIndex = GetFieldIndex(name, index); + return GetField(type, fieldIndex, converter); + } + + /// + public virtual T? GetField(int index) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(); + return GetField(index, converter); + } + + /// + public virtual T? GetField(string name) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(); + return GetField(name, converter); + } + + /// + public virtual T? GetField(string name, int index) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(); + return GetField(name, index, converter); + } + + /// + public virtual T? GetField(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); + } + + /// + public virtual T? GetField(string name, ITypeConverter converter) + { + CheckHasBeenRead(); + + var index = GetFieldIndex(name); + return GetField(index, converter); + } + + /// + public virtual T? GetField(string name, int index, ITypeConverter converter) + { + CheckHasBeenRead(); + + var fieldIndex = GetFieldIndex(name, index); + return GetField(fieldIndex, converter); + } + + /// + public virtual T? GetField(int index) where TConverter : ITypeConverter + { + CheckHasBeenRead(); + + var converter = ObjectResolver.Current.Resolve(); + return GetField(index, converter); + } + + /// + public virtual T? GetField(string name) where TConverter : ITypeConverter + { + CheckHasBeenRead(); + + var converter = ObjectResolver.Current.Resolve(); + return GetField(name, converter); + } + + /// + public virtual T? GetField(string name, int index) where TConverter : ITypeConverter + { + CheckHasBeenRead(); + + var converter = ObjectResolver.Current.Resolve(); + return GetField(name, index, converter); + } + + /// + 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); + } + + /// + 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); + } + + /// + 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); + } + + /// + 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; + } + } + + /// + 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); + } + + /// + 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); + } + + /// + public virtual bool TryGetField(int index, out T? field) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(); + return TryGetField(index, converter, out field); + } + + /// + public virtual bool TryGetField(string name, out T? field) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(); + return TryGetField(name, converter, out field); + } + + /// + public virtual bool TryGetField(string name, int index, out T? field) + { + CheckHasBeenRead(); + + var converter = context.TypeConverterCache.GetConverter(); + return TryGetField(name, index, converter, out field); + } + + /// + public virtual bool TryGetField(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(index, converter); + return true; + } + catch + { + field = default; + return false; + } + } + + /// + public virtual bool TryGetField(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); + } + + /// + public virtual bool TryGetField(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); + } + + /// + public virtual bool TryGetField(int index, out T? field) where TConverter : ITypeConverter + { + CheckHasBeenRead(); + + var converter = ObjectResolver.Current.Resolve(); + return TryGetField(index, converter, out field); + } + + /// + public virtual bool TryGetField(string name, out T? field) where TConverter : ITypeConverter + { + CheckHasBeenRead(); + + var converter = ObjectResolver.Current.Resolve(); + return TryGetField(name, converter, out field); + } + + /// + public virtual bool TryGetField(string name, int index, out T? field) where TConverter : ITypeConverter + { + CheckHasBeenRead(); + + var converter = ObjectResolver.Current.Resolve(); + return TryGetField(name, index, converter, out field); + } + + /// + public virtual T? GetRecord() + { + CheckHasBeenRead(); + + if (headerRecord == null && hasHeaderRecord) + { + ReadHeader(); + ValidateHeader(); + + if (!Read()) + { + return default; + } + } + + T record; + try + { + record = recordManager.Value.Create(); + } + 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; + } + + /// + public virtual T? GetRecord(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(); + } + + /// + 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; + } + + /// + public virtual IEnumerable GetRecords() + { + if (disposed) + { + throw new ObjectDisposedException(nameof(CsvReader), + "GetRecords() returns an IEnumerable 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(); + } + + while (Read()) + { + T record; + try + { + record = recordManager.Value.Create(); + } + 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; + } + } + + /// + public virtual IEnumerable GetRecords(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(); + } + + /// + public virtual IEnumerable GetRecords(Type type) + { + if (disposed) + { + throw new ObjectDisposedException(nameof(CsvReader), + "GetRecords() returns an IEnumerable 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; + } + } + + /// + public virtual IEnumerable EnumerateRecords(T record) + { + if (disposed) + { + throw new ObjectDisposedException(nameof(CsvReader), + "GetRecords() returns an IEnumerable 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(); + } + + 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 + /// + public virtual async IAsyncEnumerable GetRecordsAsync([EnumeratorCancellation] CancellationToken cancellationToken = default(CancellationToken)) + { + if (disposed) + { + throw new ObjectDisposedException(nameof(CsvReader), + "GetRecords() returns an IEnumerable 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(); + } + + while (await ReadAsync().ConfigureAwait(false)) + { + cancellationToken.ThrowIfCancellationRequested(); + T record; + try + { + record = recordManager.Value.Create(); + } + 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; + } + } + + /// + public virtual IAsyncEnumerable GetRecordsAsync(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(cancellationToken); + } + + /// + public virtual async IAsyncEnumerable GetRecordsAsync(Type type, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + if (disposed) + { + throw new ObjectDisposedException(nameof(CsvReader), + "GetRecords() returns an IEnumerable 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; + } + } + + /// + public virtual async IAsyncEnumerable EnumerateRecordsAsync(T record, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + if (disposed) + { + throw new ObjectDisposedException(nameof(CsvReader), + "GetRecords() returns an IEnumerable 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(); + } + + 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 + + /// + /// Gets the index of the field with the given name. + /// + /// The name of the field. + /// The index of the field. + /// Indicates if a TryGet is executed. + /// The index of the field. + public virtual int GetFieldIndex(string name, int index = 0, bool isTryGet = false) + { + return GetFieldIndex(new[] { name }, index, isTryGet); + } + + /// + /// Gets the index of the field with the given name. + /// + /// The names of the field. + /// The index of the field. + /// Indicates if a TryGet is executed. + /// Indicates if the field is optional. + /// The index of the field. + public virtual int GetFieldIndex(IEnumerable names, int index = 0, bool isTryGet = false, bool isOptional = false) + { + 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]; + } + + /// + /// Indicates if values can be read. + /// + /// The member map. + /// True if values can be read. + 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; + } + + /// + /// Indicates if values can be read. + /// + /// The member reference map. + /// True if values can be read. + 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; + } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes the object. + /// + /// Indicates if the object is being disposed. + 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; + } + + /// + /// Checks if the file has been read. + /// + /// Thrown when the file has not yet been read. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected virtual void CheckHasBeenRead() + { + if (!hasBeenRead) + { + throw new ReaderException(context, "You must call read on the reader before accessing its data."); + } + } + + /// + /// Parses the named indexes. + /// + /// Thrown when no header record was found. + [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 { 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 +{ + /// + /// Used to write CSV files. + /// + public class CsvWriter : IWriter + { + private readonly TextWriter writer; + private readonly CsvContext context; + private readonly Lazy recordManager; + private readonly TypeConverterCache typeConverterCache; + private readonly TrimOptions trimOptions; + private readonly ShouldQuote shouldQuote; + private readonly MemberMapData reusableMemberMapData = new MemberMapData(null); + private readonly Dictionary typeConverterOptionsCache = new Dictionary(); + 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 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; + + /// + public virtual string[] HeaderRecord { get; private set; } + + /// + public virtual int Row => row; + + /// + public virtual int Index => index; + + /// + public virtual CsvContext Context => context; + + /// + public virtual IWriterConfiguration Configuration { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The writer. + /// The culture. + /// true to leave the open after the object is disposed, otherwise false. + public CsvWriter(TextWriter writer, CultureInfo culture, bool leaveOpen = false) : this(writer, new CsvConfiguration(culture), leaveOpen) { } + + /// + /// Initializes a new instance of the class. + /// + /// The writer. + /// The configuration. + /// true to leave the open after the object is disposed, otherwise false. + 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(() => ObjectResolver.Current.Resolve(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]; + } + + /// + public virtual void WriteConvertedField(string field, Type fieldType) + { + this.fieldType = fieldType; + + if (field == null) + { + return; + } + + WriteField(field); + } + + /// + 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); + } + + /// + 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; + } + + /// + public virtual void WriteField(T field) + { + var type = field == null ? typeof(string) : field.GetType(); + var converter = typeConverterCache.GetConverter(type); + WriteField(field, converter); + } + + /// + public virtual void WriteField(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); + } + + /// + public virtual void WriteField(T field) + { + var converter = typeConverterCache.GetConverter(); + + WriteField(field, converter); + } + + /// + public virtual void WriteComment(string text) + { + WriteField(comment + text, false); + } + + /// + public virtual void WriteHeader() + { + WriteHeader(typeof(T)); + } + + /// + 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(); + + 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; + } + + /// + /// Writes a dynamic header record. + /// + /// The header record to write. + /// Thrown when no record is passed. + 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; + } + + /// + public virtual void WriteRecord(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); + } + } + + /// + public virtual void WriteRecords(IEnumerable records) + { + // Changes in this method require changes in method WriteRecords(IEnumerable 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); + } + } + + /// + public virtual void WriteRecords(IEnumerable 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); + } + } + + /// + public virtual async Task WriteRecordsAsync(IEnumerable records, CancellationToken cancellationToken = default) + { + // These methods should all be the same; + // - WriteRecordsAsync(IEnumerable records) + // - WriteRecordsAsync(IEnumerable records) + // - WriteRecordsAsync(IAsyncEnumerable 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); + } + } + + /// + public virtual async Task WriteRecordsAsync(IEnumerable records, CancellationToken cancellationToken = default) + { + // These methods should all be the same; + // - WriteRecordsAsync(IEnumerable records) + // - WriteRecordsAsync(IEnumerable records) + // - WriteRecordsAsync(IAsyncEnumerable 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 + /// + public virtual async Task WriteRecordsAsync(IAsyncEnumerable records, CancellationToken cancellationToken = default) + { + // These methods should all be the same; + // - WriteRecordsAsync(IEnumerable records) + // - WriteRecordsAsync(IEnumerable records) + // - WriteRecordsAsync(IAsyncEnumerable 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 + + /// + public virtual void NextRecord() + { + WriteToBuffer(newLine); + FlushBuffer(); + + index = 0; + row++; + } + + /// + public virtual async Task NextRecordAsync() + { + WriteToBuffer(newLine); + await FlushBufferAsync().ConfigureAwait(false); + + index = 0; + row++; + } + + /// + public virtual void Flush() + { + FlushBuffer(); + writer.Flush(); + } + + /// + public virtual async Task FlushAsync() + { + await FlushBufferAsync().ConfigureAwait(false); + await writer.FlushAsync().ConfigureAwait(false); + } + + /// + /// Flushes the buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected virtual void FlushBuffer() + { + writer.Write(buffer, 0, bufferPosition); + bufferPosition = 0; + } + + /// + /// Asynchronously flushes the buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected virtual async Task FlushBufferAsync() + { + await writer.WriteAsync(buffer, 0, bufferPosition).ConfigureAwait(false); + bufferPosition = 0; + } + + /// + /// Indicates if values can be written. + /// + /// The member map. + /// True if values can be written. + 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; + } + + /// + /// Determines the type for the given record. + /// + /// The type of the record. + /// The record to determine the type of. + /// The System.Type for the record. + public virtual Type GetTypeForRecord(T record) + { + var type = typeof(T); + if (type == typeof(object)) + { + type = record.GetType(); + } + + return type; + } + + /// + /// Sanitizes the given field, before it is injected. + /// + /// The field to sanitize. + /// The sanitized field. + /// Thrown when an injection character is found in the field. + [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; + } + + /// + /// Writes the given value to the buffer. + /// + /// The value to write. + [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; + } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes the object. + /// + /// Indicates if the object is being disposed. + 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 + /// + public async ValueTask DisposeAsync() + { + await DisposeAsync(true).ConfigureAwait(false); + GC.SuppressFinalize(this); + } + + /// + 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 WriteHeaderAsync(IAsyncEnumerable 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(IEnumerable 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 +{ + /// + /// Function that gets called when bad data is found. + /// + /// The args. + public delegate void BadDataFound(BadDataFoundArgs args); + + /// + /// Information about the field that caused to be called. + /// + public readonly struct BadDataFoundArgs + { + /// + /// The full field unedited. + /// + public readonly string Field; + + /// + /// The full row unedited. + /// + public readonly string RawRecord; + + /// + /// The context. + /// + public readonly CsvContext Context; + + /// + /// Creates a new instance of BadDataFoundArgs. + /// + /// The full field unedited. + /// The full row unedited. + /// The context. + 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 +{ + /// + /// Function that converts a string into an object. + /// + /// The type of the member. + /// The args. + /// The class object. + public delegate TMember ConvertFromString(ConvertFromStringArgs args); + + /// + /// args. + /// + public readonly struct ConvertFromStringArgs + { + /// + /// The row. + /// + public readonly IReaderRow Row; + + /// + /// Creates a new instance of ConvertFromStringArgs. + /// + /// The row. + 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 +{ + /// + /// Function that converts an object into a string. + /// + /// The type of the class. + /// The args. + /// The string. + public delegate string ConvertToString(ConvertToStringArgs args); + + /// + /// args. + /// + /// The value to convert. + public readonly struct ConvertToStringArgs + { + /// + /// The value to convert. + /// + public readonly TClass Value; + + /// + /// Creates a new instance of ConvertToStringArgs{TClass}. + /// + /// The value to convert. + 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 +{ + /// + /// Function that chooses the constructor to use for constructor mapping. + /// + public delegate ConstructorInfo GetConstructor(GetConstructorArgs args); + + /// + /// GetConstructor args. + /// + public readonly struct GetConstructorArgs + { + /// + /// The class type. + /// + public readonly Type ClassType; + + /// + /// Creates a new instance of GetConstructorArgs. + /// + /// The class type. + 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 +{ + /// + /// Function that resolves the delimiter from the given text. + /// Returns null if no delimiter is found. + /// + /// + /// + public delegate string? GetDelimiter(GetDelimiterArgs args); + + /// + /// GetDelimiter args. + /// + public readonly struct GetDelimiterArgs + { + /// + /// The text to resolve the delimiter from. + /// + public readonly string Text; + + /// + /// The configuration. + /// + public readonly IParserConfiguration Configuration; + + /// + /// Creates an instance of GetDelimiterArgs. + /// + /// The text to resolve the delimiter from. + /// The configuration. + 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 +{ + /// + /// Function that gets the name to use for the property of the dynamic object. + /// + public delegate string GetDynamicPropertyName(GetDynamicPropertyNameArgs args); + + /// + /// GetDynamicPropertyName args. + /// + public readonly struct GetDynamicPropertyNameArgs + { + /// + /// The field index. + /// + public readonly int FieldIndex; + + /// + /// The context. + /// + public readonly CsvContext Context; + + /// + /// Creates a new instance of GetDynamicPropertyNameArgs. + /// + /// The field index. + /// The context. + 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 +{ + /// + /// Function that is called when a header validation check is ran. The default function + /// will throw a if there is no header for a given member mapping. + /// You can supply your own function to do other things like logging the issue instead of throwing an exception. + /// + public delegate void HeaderValidated(HeaderValidatedArgs args); + + /// + /// HeaderValidated args. + /// + public readonly struct HeaderValidatedArgs + { + /// + /// The invalid headers. + /// + public readonly InvalidHeader[] InvalidHeaders; + + /// + /// The context. + /// + public readonly CsvContext Context; + + /// + /// Creates a new instance of HeaderValidatedArgs. + /// + /// The invalid headers. + /// The context. + 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 +{ + /// + /// Function that is called when a missing field is found. The default function will + /// throw a . You can supply your own function to do other things + /// like logging the issue instead of throwing an exception. + /// + public delegate void MissingFieldFound(MissingFieldFoundArgs args); + + /// + /// MissingFieldFound args. + /// + public readonly struct MissingFieldFoundArgs + { + /// + /// The header names. + /// + public readonly string[]? HeaderNames; + + /// + /// The index. + /// + public readonly int Index; + + /// + /// The context. + /// + public readonly CsvContext Context; + + /// + /// Creates a new instance of MissingFieldFoundArgs. + /// + /// The header names. + /// The index. + /// The context. + 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 +{ + /// + /// 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. + /// + public delegate string PrepareHeaderForMatch(PrepareHeaderForMatchArgs args); + + /// + /// PrepareHeaderForMatch args. + /// + public readonly struct PrepareHeaderForMatchArgs + { + /// + /// The header. + /// + public readonly string Header; + + /// + /// The field index. + /// + public readonly int FieldIndex; + + /// + /// Creates a new instance of PrepareHeaderForMatchArgs. + /// + /// The header. + /// The field index. + 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 +{ + /// + /// 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. + /// + public delegate bool ReadingExceptionOccurred(ReadingExceptionOccurredArgs args); + + /// + /// ReadingExceptionOccurred args. + /// + public readonly struct ReadingExceptionOccurredArgs + { + /// + /// The exception. + /// + public readonly CsvHelperException Exception; + + /// + /// Creates a new instance of ReadingExceptionOccurredArgs. + /// + /// The exception. + 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 +{ + /// + /// Function that will return the prefix for a reference header. + /// + public delegate string ReferenceHeaderPrefix(ReferenceHeaderPrefixArgs args); + + /// + /// ReferenceHeaderPrefix args. + /// + public readonly struct ReferenceHeaderPrefixArgs + { + /// + /// The member type. + /// + public readonly Type MemberType; + + /// + /// The member name. + /// + public readonly string MemberName; + + /// + /// Creates a new instance of ReferenceHeaderPrefixArgs. + /// + /// The member type. + /// The member name. + 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 +{ + /// + /// Function that is used to determine if a field should get quoted when writing. + /// + public delegate bool ShouldQuote(ShouldQuoteArgs args); + + /// + /// ShouldQuote args. + /// + public readonly struct ShouldQuoteArgs + { + /// + /// The field. + /// + public readonly string Field; + + /// + /// The field type. + /// + public readonly Type FieldType; + + /// + /// The row. + /// + public readonly IWriterRow Row; + + /// + /// Creates a new instance of ShouldQuoteArgs. + /// + /// The field. + /// The field type. + /// The row. + 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 +{ + /// + /// Function that determines whether to skip the given record or not. + /// + public delegate bool ShouldSkipRecord(ShouldSkipRecordArgs args); + + /// + /// ShouldSkipRecord args. + /// + public readonly struct ShouldSkipRecordArgs + { + /// + /// The record. + /// + public readonly IReaderRow Row; + + /// + /// Creates a new instance of ShouldSkipRecordArgs. + /// + /// The row. + 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 +{ + /// + /// Function that determines if constructor parameters should be used to create + /// the class instead of the default constructor and members. + /// + public delegate bool ShouldUseConstructorParameters(ShouldUseConstructorParametersArgs args); + + /// + /// ShouldUseConstructorParameters args. + /// + public readonly struct ShouldUseConstructorParametersArgs + { + /// + /// The parameter type. + /// + public readonly Type ParameterType; + + /// + /// Creates a new instance of ShouldUseConstructorParametersArgs. + /// + /// The parameter type. + 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 +{ + /// + /// Function that validates a field. + /// + /// The args. + /// true if the field is valid, otherwise false. + public delegate bool Validate(ValidateArgs args); + + /// + /// Function that gets the exception message when validation fails. + /// + /// The args. + /// The exception message. + public delegate string ValidateMessage(ValidateArgs args); + + /// + /// Validate args. + /// + public readonly struct ValidateArgs + { + /// + /// The field. + /// + public readonly string Field; + + /// + /// The row. + /// + public readonly IReaderRow Row; + + /// + /// Creates a new instance of ValidateArgs. + /// + /// The field. + /// The row. + 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 FirstOrDefaultAsync(this IAsyncEnumerable 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 +{ + /// + /// Creates dynamic records. + /// + public class DynamicRecordCreator : RecordCreator + { + /// + /// Initializes a new instance. + /// + /// The reader. + public DynamicRecordCreator(CsvReader reader) : base(reader) { } + + /// + /// Creates a of type + /// that will create a record of the given type using the current + /// reader row. + /// + /// The record type. + protected override Delegate CreateCreateRecordDelegate(Type recordType) => (Func)CreateDynamicRecord; + + /// + /// Creates a dynamic record of the current reader row. + /// + protected virtual dynamic CreateDynamicRecord() + { + var obj = new ExpandoObject(); + var dict = obj as IDictionary; + 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 +{ + /// + /// Write dynamic records. + /// + public class DynamicRecordWriter : RecordWriter + { + private readonly Hashtable getters = new Hashtable(); + + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public DynamicRecordWriter(CsvWriter writer) : base(writer) { } + + /// + /// Creates a of type + /// that will write the given record using the current writer row. + /// + /// The record type. + /// The record. + protected override Action CreateWriteDelegate(T record) + { + // http://stackoverflow.com/a/14011692/68499 + + Action 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>)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>.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 +{ + /// + /// Writes expando objects. + /// + public class ExpandoObjectRecordWriter : RecordWriter + { + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public ExpandoObjectRecordWriter(CsvWriter writer) : base(writer) { } + + /// + /// Creates a of type + /// that will write the given record using the current writer row. + /// + /// The record type. + /// The record. + protected override Action CreateWriteDelegate(T record) + { + Action action = r => + { + var dict = ((IDictionary)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 +{ + /// + /// Manages expression creation. + /// + public class ExpressionManager + { + private readonly CsvReader reader; + private readonly CsvWriter writer; + + /// + /// Initializes a new instance using the given reader. + /// + /// The reader. + public ExpressionManager(CsvReader reader) + { + this.reader = reader; + } + + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public ExpressionManager(CsvWriter writer) + { + this.writer = writer; + } + + /// + /// Creates the constructor arguments used to create a type. + /// + /// The mapping to create the arguments for. + /// The arguments that will be added to the mapping. + public virtual void CreateConstructorArgumentExpressionsForMapping(ClassMap map, List 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(); + 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(); + 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); + } + } + } + + /// + /// Creates the member assignments for the given . + /// + /// The mapping to create the assignments for. + /// The assignments that will be added to from the mapping. + public virtual void CreateMemberAssignmentsForMapping(ClassMap mapping, List 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(); + 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(); + CreateMemberAssignmentsForMapping(referenceMap.Data.Mapping, referenceAssignments); + referenceBody = CreateInstanceAndAssignMembers(referenceMap.Data.Member.MemberType(), referenceAssignments); + } + + assignments.Add(Expression.Bind(referenceMap.Data.Member, referenceBody)); + } + } + + /// + /// Creates an expression the represents getting the field for the given + /// member and converting it to the member's type. + /// + /// The mapping for the member. + 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; + } + + /// + /// 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. + /// + /// The current member expression. + /// The mapping to look for the member to map on. + /// The member map to look for on the mapping. + /// An Expression to access the given member. + 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; + } + + /// + /// Creates an instance of the given type using , then assigns + /// the given member assignments to that instance. + /// + /// The type of the record we're creating. + /// The member assignments that will be assigned to the created instance. + /// A representing the instance creation and assignments. + public virtual BlockExpression CreateInstanceAndAssignMembers(Type recordType, List assignments) + { + var expressions = new List(); + 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; + } + + /// + /// Creates an expression that converts the field expression using a type converter. + /// + /// The mapping for the member. + /// The field expression. + 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; + } + + /// + /// Creates an expression that converts the field expression using a type converter. + /// + /// The mapping for the parameter. + /// The field expression. + 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; + } + + /// + /// Creates a default expression if field expression is empty. + /// + /// The mapping for the member. + /// The field expression. + 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; + } + + /// + /// Creates a default expression if field expression is empty. + /// + /// The mapping for the parameter. + /// The field expression. + 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 +{ + /// + /// Creates objects. + /// + public class ObjectRecordCreator : RecordCreator + { + /// + /// Initializes a new instance using the given reader. + /// + /// + public ObjectRecordCreator(CsvReader reader) : base(reader) { } + + /// + /// Creates a of type + /// that will create a record of the given type using the current + /// reader row. + /// + /// The record type. + 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(); + ExpressionManager.CreateConstructorArgumentExpressionsForMapping(map, arguments); + + var args = new GetConstructorArgs(map.ClassType); + body = Expression.New(Reader.Configuration.GetConstructor(args), arguments); + } + else + { + var assignments = new List(); + 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 +{ + /// + /// Writes objects. + /// + public class ObjectRecordWriter : RecordWriter + { + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public ObjectRecordWriter(CsvWriter writer) : base(writer) { } + + /// + /// Creates a of type + /// that will write the given record using the current writer row. + /// + /// The record type. + /// The record. + protected override Action CreateWriteDelegate(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>(); + + foreach (var memberMap in members) + { + if (memberMap.Data.WritingConvertExpression != null) + { + // The user is providing the expression to do the conversion. + var constructor = typeof(ConvertToStringArgs).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>(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>(writeFieldMethodCall, recordParameter).Compile()); + } + + var action = CombineDelegates(delegates) ?? new Action((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 +{ + /// + /// Creates primitive records. + /// + public class PrimitiveRecordCreator : RecordCreator + { + /// + /// Initializes a new instance using the given reader. + /// + /// The reader. + public PrimitiveRecordCreator(CsvReader reader) : base(reader) { } + + /// + /// Creates a of type + /// that will create a record of the given type using the current + /// reader row. + /// + /// The record type. + 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 +{ + /// + /// Writes primitives. + /// + public class PrimitiveRecordWriter : RecordWriter + { + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public PrimitiveRecordWriter(CsvWriter writer) : base(writer) { } + + /// + /// Creates a of type + /// that will write the given record using the current writer row. + /// + /// The record type. + /// The record. + protected override Action CreateWriteDelegate(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>(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 +{ + /// + /// Base implementation for classes that create records. + /// + public abstract class RecordCreator + { + private readonly Dictionary createRecordFuncs = new Dictionary(); + + /// + /// The reader. + /// + protected CsvReader Reader { get; private set; } + + /// + /// The expression manager. + /// + protected ExpressionManager ExpressionManager { get; private set; } + + /// + /// Initializes a new instance using the given reader. + /// + /// The reader. + public RecordCreator(CsvReader reader) + { + Reader = reader; + ExpressionManager = new ExpressionManager(reader); + } + + /// + /// Create a record of the given type using the current row. + /// + /// The record type. + public T Create() + { + try + { + return ((Func)GetCreateRecordDelegate(typeof(T))).Invoke(); + } + catch (TargetInvocationException ex) + { + if (ex.InnerException != null) + { + throw ex.InnerException; + } + else + { + throw; + } + } + } + + /// + /// Create a record of the given type using the current row. + /// + /// The record type. + public object? Create(Type recordType) + { + try + { + return GetCreateRecordDelegate(recordType).DynamicInvoke(); + } + catch (TargetInvocationException ex) + { + if (ex.InnerException != null) + { + throw ex.InnerException; + } + else + { + throw; + } + } + } + + /// + /// Gets the delegate to create a record for the given record type. + /// If the delegate doesn't exist, one will be created and cached. + /// + /// The record type. + protected virtual Delegate GetCreateRecordDelegate(Type recordType) + { + if (!createRecordFuncs.TryGetValue(recordType, out Delegate func)) + { + createRecordFuncs[recordType] = func = CreateCreateRecordDelegate(recordType); + } + + return func; + } + + /// + /// Creates a of type + /// that will create a record of the given type using the current + /// reader row. + /// + /// The record type. + 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 +{ + /// + /// Factory to create record creators. + /// + public class RecordCreatorFactory + { + private readonly CsvReader reader; + private readonly DynamicRecordCreator dynamicRecordCreator; + private readonly PrimitiveRecordCreator primitiveRecordCreator; + private readonly ObjectRecordCreator objectRecordCreator; + + /// + /// Initializes a new instance using the given reader. + /// + /// The reader. + public RecordCreatorFactory(CsvReader reader) + { + this.reader = reader; + dynamicRecordCreator = new DynamicRecordCreator(reader); + primitiveRecordCreator = new PrimitiveRecordCreator(reader); + objectRecordCreator = new ObjectRecordCreator(reader); + } + + /// + /// Creates a record creator for the given record type. + /// + /// The record type. + 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 +{ + /// + /// Hydrates members of an existing record. + /// + public class RecordHydrator + { + private readonly CsvReader reader; + private readonly ExpressionManager expressionManager; + private readonly Dictionary hydrateRecordActions = new Dictionary(); + + /// + /// Creates a new instance using the given reader. + /// + /// The reader. + public RecordHydrator(CsvReader reader) + { + this.reader = reader; + expressionManager = ObjectResolver.Current.Resolve(reader); + } + + /// + /// Hydrates members of the given record using the current reader row. + /// + /// The record type. + /// The record. + public void Hydrate(T record) + { + try + { + GetHydrateRecordAction()(record); + } + catch (TargetInvocationException ex) + { + if (ex.InnerException != null) + { + throw ex.InnerException; + } + else + { + throw; + } + } + } + + /// + /// Gets the action delegate used to hydrate a custom class object's members with data from the reader. + /// + /// The record type. + protected virtual Action GetHydrateRecordAction() + { + var recordType = typeof(T); + + if (!hydrateRecordActions.TryGetValue(recordType, out Delegate action)) + { + hydrateRecordActions[recordType] = action = CreateHydrateRecordAction(); + } + + return (Action)action; + } + + /// + /// Creates the action delegate used to hydrate a record's members with data from the reader. + /// + /// The record type. + protected virtual Action CreateHydrateRecordAction() + { + 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(); + + 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(); + 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>(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 +{ + /// + /// Manages record manipulation. + /// + public class RecordManager + { + private readonly CsvReader reader; + private readonly RecordCreatorFactory recordCreatorFactory; + private readonly RecordHydrator recordHydrator; + private readonly RecordWriterFactory recordWriterFactory; + + /// + /// Initializes a new instance using the given reader. + /// + /// + public RecordManager(CsvReader reader) + { + this.reader = reader; + recordCreatorFactory = ObjectResolver.Current.Resolve(reader); + recordHydrator = ObjectResolver.Current.Resolve(reader); + } + + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public RecordManager(CsvWriter writer) + { + recordWriterFactory = ObjectResolver.Current.Resolve(writer); + } + + /// + /// Creates a record of the given type using the current reader row. + /// + /// The type of record to create. + public T Create() + { + var recordCreator = recordCreatorFactory.MakeRecordCreator(typeof(T)); + return recordCreator.Create(); + } + + /// + /// Creates a record of the given type using the current reader row. + /// + /// The type of record to create. + public object? Create(Type recordType) + { + var recordCreator = recordCreatorFactory.MakeRecordCreator(recordType); + return recordCreator.Create(recordType); + } + + /// + /// Hydrates the given record using the current reader row. + /// + /// The type of the record. + /// The record to hydrate. + public void Hydrate(T record) + { + recordHydrator.Hydrate(record); + } + + /// + /// Writes the given record to the current writer row. + /// + /// The type of the record. + /// The record. + public void Write(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 +{ + /// + /// Base implementation for classes that write records. + /// + public abstract class RecordWriter + { + private readonly Dictionary typeActions = new Dictionary(); + + /// + /// Gets the writer. + /// + protected CsvWriter Writer { get; private set; } + + /// + /// The expression manager. + /// + protected ExpressionManager ExpressionManager { get; private set; } + + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public RecordWriter(CsvWriter writer) + { + Writer = writer; + ExpressionManager = ObjectResolver.Current.Resolve(writer); + } + + /// + /// Writes the record to the current row. + /// + /// Type of the record. + /// The record. + public void Write(T record) + { + try + { + GetWriteDelegate(record)(record); + } + catch (TargetInvocationException ex) + { + if (ex.InnerException != null) + { + throw ex.InnerException; + } + else + { + throw; + } + } + } + + /// + /// Gets the delegate to write the given record. + /// If the delegate doesn't exist, one will be created and cached. + /// + /// The record type. + /// The record. + protected Action GetWriteDelegate(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)action; + } + + /// + /// Creates a of type + /// that will write the given record using the current writer row. + /// + /// The record type. + /// The record. + protected abstract Action CreateWriteDelegate(T record); + + /// + /// Combines the delegates into a single multicast delegate. + /// This is needed because Silverlight doesn't have the + /// Delegate.Combine( params Delegate[] ) overload. + /// + /// The delegates to combine. + /// A multicast delegate combined from the given delegates. + protected virtual Action CombineDelegates(IEnumerable> delegates) + { + return (Action)delegates.Aggregate(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 +{ + /// + /// Factory to create record writers. + /// + public class RecordWriterFactory + { + private readonly CsvWriter writer; + private readonly ExpandoObjectRecordWriter expandoObjectRecordWriter; + private readonly DynamicRecordWriter dynamicRecordWriter; + private readonly PrimitiveRecordWriter primitiveRecordWriter; + private readonly ObjectRecordWriter objectRecordWriter; + + /// + /// Initializes a new instance using the given writer. + /// + /// The writer. + public RecordWriterFactory(CsvWriter writer) + { + this.writer = writer; + expandoObjectRecordWriter = new ExpandoObjectRecordWriter(writer); + dynamicRecordWriter = new DynamicRecordWriter(writer); + primitiveRecordWriter = new PrimitiveRecordWriter(writer); + objectRecordWriter = new ObjectRecordWriter(writer); + } + + /// + /// Creates a new record writer for the given record. + /// + /// The type of the record. + /// The record. + public virtual RecordWriter MakeRecordWriter(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 +{ + /// + /// Creates CsvHelper classes. + /// + public class Factory : IFactory + { + /// + /// Creates an . + /// + /// The text reader to use for the csv parser. + /// The configuration to use for the csv parser. + /// The created parser. + public virtual IParser CreateParser(TextReader reader, Configuration.CsvConfiguration configuration) + { + return new CsvParser(reader, configuration); + } + + /// + /// Creates an . + /// + /// The text reader to use for the csv parser. + /// The culture information. + /// + /// The created parser. + /// + public virtual IParser CreateParser(TextReader reader, CultureInfo cultureInfo) + { + return new CsvParser(reader, cultureInfo); + } + + /// + /// Creates an . + /// + /// The text reader to use for the csv reader. + /// The configuration to use for the reader. + /// The created reader. + public virtual IReader CreateReader(TextReader reader, Configuration.CsvConfiguration configuration) + { + return new CsvReader(reader, configuration); + } + + /// + /// Creates an . + /// + /// The text reader to use for the csv reader. + /// The culture information. + /// + /// The created reader. + /// + public virtual IReader CreateReader(TextReader reader, CultureInfo cultureInfo) + { + return new CsvReader(reader, cultureInfo); + } + + /// + /// Creates an . + /// + /// The parser used to create the reader. + /// The created reader. + public virtual IReader CreateReader(IParser parser) + { + return new CsvReader(parser); + } + + /// + /// Creates an . + /// + /// The text writer to use for the csv writer. + /// The configuration to use for the writer. + /// The created writer. + public virtual IWriter CreateWriter(TextWriter writer, Configuration.CsvConfiguration configuration) + { + return new CsvWriter(writer, configuration); + } + + /// + /// Creates an . + /// + /// The text writer to use for the csv writer. + /// The culture information. + /// + /// The created writer. + /// + public virtual IWriter CreateWriter(TextWriter writer, CultureInfo cultureInfo) + { + return new CsvWriter(writer, cultureInfo); + } + + /// + /// Access point for fluent interface to dynamically build a + /// + /// Type you will be making a class map for + /// Options to further configure the + public IHasMap CreateClassMapBuilder() + { + return new ClassMapBuilder(); + } + } +} 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 +{ + /// + /// Caches fields. + /// Based on C#'s . + /// + 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(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 +{ + /// + /// Represents a user supplied field validation failure. + /// + public class FieldValidationException : ValidationException + { + /// + /// Gets the field that failed validation. + /// + public string Field { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The reading context. + /// The field that failed validation. + public FieldValidationException(CsvContext context, string field) : base(context) + { + Field = field; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The reading context. + /// The field that failed validation. + /// The message that describes the error. + public FieldValidationException(CsvContext context, string field, string message) : base(context, message) + { + Field = field; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The reading context. + /// The field that failed validation. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public 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 +{ + /// + /// Represents a header validation failure. + /// + public class HeaderValidationException : ValidationException + { + /// + /// Gets the invalid headers. + /// + public InvalidHeader[] InvalidHeaders { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The reading context. + /// The invalid headers. + public HeaderValidationException(CsvContext context, InvalidHeader[] invalidHeaders) : base(context) + { + InvalidHeaders = invalidHeaders; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The reading context. + /// The invalid headers. + /// The message that describes the error. + public HeaderValidationException(CsvContext context, InvalidHeader[] invalidHeaders, string message) : base(context, message) + { + InvalidHeaders = invalidHeaders; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The reading context. + /// The invalid headers. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public 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 +{ + /// + /// Defines methods used to create + /// CsvHelper classes. + /// + public interface IFactory + { + /// + /// Creates an . + /// + /// The text reader to use for the csv parser. + /// The configuration to use for the csv parser. + /// The created parser. + IParser CreateParser(TextReader reader, Configuration.CsvConfiguration configuration); + + /// + /// Creates an . + /// + /// The text reader to use for the csv parser. + /// The culture information. + /// + /// The created parser. + /// + IParser CreateParser(TextReader reader, CultureInfo cultureInfo); + + /// + /// Creates an . + /// + /// The text reader to use for the csv reader. + /// The configuration to use for the reader. + /// The created reader. + IReader CreateReader(TextReader reader, Configuration.CsvConfiguration configuration); + + /// + /// Creates an . + /// + /// The text reader to use for the csv reader. + /// The culture information. + /// + /// The created reader. + /// + IReader CreateReader(TextReader reader, CultureInfo cultureInfo); + + /// + /// Creates an . + /// + /// The parser used to create the reader. + /// The created reader. + IReader CreateReader(IParser parser); + + /// + /// Creates an . + /// + /// The text writer to use for the csv writer. + /// The configuration to use for the writer. + /// The created writer. + IWriter CreateWriter(TextWriter writer, Configuration.CsvConfiguration configuration); + + /// + /// Creates an . + /// + /// The text writer to use for the csv writer. + /// The culture information. + /// + /// The created writer. + /// + IWriter CreateWriter(TextWriter writer, CultureInfo cultureInfo); + + /// + /// Provides a fluent interface for dynamically creating s + /// + /// Type of class to map + /// Next available options + IHasMap CreateClassMapBuilder(); + } +} 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 +{ + /// + /// Defines the functionality of a class that creates objects + /// from a given type. + /// + public interface IObjectResolver + { + /// + /// A value indicating if the resolver's + /// returns false that an object will still be created using + /// CsvHelper's object creation. True to fallback, otherwise false. + /// Default value is true. + /// + bool UseFallback { get; } + + /// + /// A value indicating if the resolver is able to resolve + /// the given type. True if the type can be resolved, + /// otherwise false. + /// + Func CanResolve { get; } + + /// + /// The function that creates an object from a given type. + /// + Func ResolveFunction { get; } + + /// + /// Creates an object from the given type using the + /// function. If is false, the object will be + /// created using CsvHelper's default object creation. If + /// is false, an exception is thrown. + /// + /// The type to create an instance from. The created object + /// may not be the same type as the given type. + /// Constructor arguments used to create the type. + object Resolve( Type type, params object[] constructorArgs ); + + /// + /// Creates an object from the given type using the + /// function. If is false, the object will be + /// created using CsvHelper's default object creation. If + /// is false, an exception is thrown. + /// + /// The type to create an instance from. The created object + /// may not be the same type as the given type. + /// Constructor arguments used to create the type. + T Resolve( 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 +{ + /// + /// Defines methods used the parse a CSV file. + /// + public interface IParser : IDisposable + { + /// + /// Gets the count of how many bytes have been read. + /// needs + /// to be enabled for this value to be populated. + /// + long ByteCount { get; } + + /// + /// Gets the count of how many characters have been read. + /// + long CharCount { get; } + + /// + /// Gets the number of fields for the current row. + /// + int Count { get; } + + /// + /// Gets the field at the specified index for the current row. + /// + /// The index. + /// The field. + string this[int index] { get; } + + /// + /// 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. + /// + string[]? Record { get; } + + /// + /// Gets the raw record for the current row. + /// + string RawRecord { get; } + + /// + /// Gets the CSV row the parser is currently on. + /// + int Row { get; } + + /// + /// Gets the raw row the parser is currently on. + /// + int RawRow { get; } + + /// + /// The delimiter the parser is using. + /// + string Delimiter { get; } + + /// + /// Gets the reading context. + /// + CsvContext Context { get; } + + /// + /// Gets the configuration. + /// + IParserConfiguration Configuration { get; } + + /// + /// Reads a record from the CSV file. + /// + /// True if there are more records to read, otherwise false. + bool Read(); + + /// + /// Reads a record from the CSV file asynchronously. + /// + /// True if there are more records to read, otherwise false. + Task 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 +{ + /// + /// Defines methods used to read parsed data + /// from a CSV file. + /// + public interface IReader : IReaderRow, IDisposable + { + /// + /// Reads the header record without reading the first row. + /// + /// True if there are more records, otherwise false. + bool ReadHeader(); + + /// + /// Advances the reader to the next record. This will not read headers. + /// You need to call then + /// for the headers to be read. + /// + /// True if there are more records, otherwise false. + bool Read(); + + /// + /// Advances the reader to the next record. This will not read headers. + /// You need to call then + /// for the headers to be read. + /// + /// True if there are more records, otherwise false. + Task ReadAsync(); + + /// + /// Gets all the records in the CSV file and + /// converts each to T. The Read method + /// should not be used when using this. + /// + /// The of the record. + /// An of records. + IEnumerable GetRecords(); + + /// + /// Gets all the records in the CSV file and converts + /// each to T. The read method + /// should not be used when using this. + /// + /// The of the record. + /// The anonymous type definition to use for the records. + /// An of records. + IEnumerable GetRecords(T anonymousTypeDefinition); + + /// + /// Gets all the records in the CSV file and + /// converts each to T. The Read method + /// should not be used when using this. + /// + /// The of the record. + /// An of records. + IEnumerable GetRecords(Type type); + + /// + /// 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. + /// + /// The type of the record. + /// The record to fill each enumeration. + /// An of records. + IEnumerable EnumerateRecords(T record); + +#if !NET45 + /// + /// Gets all the records in the CSV file and + /// converts each to T. The Read method + /// should not be used when using this. + /// + /// The of the record. + /// The cancellation token to stop the writing. + /// An of records. + IAsyncEnumerable GetRecordsAsync(CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// Gets all the records in the CSV file and converts + /// each to T. The read method + /// should not be used when using this. + /// + /// The of the record. + /// The anonymous type definition to use for the records. + /// The cancellation token to stop the writing. + /// An of records. + IAsyncEnumerable GetRecordsAsync(T anonymousTypeDefinition, CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// Gets all the records in the CSV file and + /// converts each to T. The Read method + /// should not be used when using this. + /// + /// The of the record. + /// The cancellation token to stop the writing. + /// An of records. + IAsyncEnumerable GetRecordsAsync(Type type, CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// 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. + /// + /// The type of the record. + /// The record to fill each enumeration. + /// /// The cancellation token to stop the writing. + /// An of records. + IAsyncEnumerable EnumerateRecordsAsync(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 +{ + /// + /// Defines methods used to read parsed data + /// from a CSV file row. + /// + public interface IReaderRow + { + /// + /// Gets the column count of the current row. + /// This should match . + /// + int ColumnCount { get; } + + /// + /// Gets the field index the reader is currently on. + /// + int CurrentIndex { get; } + + /// + /// Gets the header record. + /// + string[]? HeaderRecord { get; } + + /// + /// Gets the parser. + /// + IParser Parser { get; } + + /// + /// Gets the reading context. + /// + CsvContext Context { get; } + + /// + /// Gets or sets the configuration. + /// + IReaderConfiguration Configuration { get; } + + /// + /// Gets the raw field at position (column) index. + /// + /// The zero based index of the field. + /// The raw field. + string? this[int index] { get; } + + /// + /// Gets the raw field at position (column) name. + /// + /// The named index of the field. + /// The raw field. + string? this[string name] { get; } + + /// + /// Gets the raw field at position (column) name. + /// + /// The named index of the field. + /// The zero based index of the field. + /// The raw field. + string? this[string name, int index] { get; } + + /// + /// Gets the raw field at position (column) index. + /// + /// The zero based index of the field. + /// The raw field. + string? GetField(int index); + + /// + /// Gets the raw field at position (column) name. + /// + /// The named index of the field. + /// The raw field. + string? GetField(string name); + + /// + /// 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. + /// + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The raw field. + string? GetField(string name, int index); + + /// + /// Gets the field converted to using + /// the specified . + /// + /// The type of the field. + /// The index of the field. + /// The field converted to . + object? GetField(Type type, int index); + + /// + /// Gets the field converted to using + /// the specified . + /// + /// The type of the field. + /// The named index of the field. + /// The field converted to . + object? GetField(Type type, string name); + + /// + /// Gets the field converted to using + /// the specified . + /// + /// The type of the field. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The field converted to . + object? GetField(Type type, string name, int index); + + /// + /// Gets the field converted to using + /// the specified . + /// + /// The type of the field. + /// The index of the field. + /// The used to convert the field to . + /// The field converted to . + object? GetField(Type type, int index, ITypeConverter converter); + + /// + /// Gets the field converted to using + /// the specified . + /// + /// The type of the field. + /// The named index of the field. + /// The used to convert the field to . + /// The field converted to . + object? GetField(Type type, string name, ITypeConverter converter); + + /// + /// Gets the field converted to using + /// the specified . + /// + /// The type of the field. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The used to convert the field to . + /// The field converted to . + object? GetField(Type type, string name, int index, ITypeConverter converter); + + /// + /// Gets the field converted to T at position (column) index. + /// + /// The of the field. + /// The zero based index of the field. + /// The field converted to T. + T? GetField(int index); + + /// + /// Gets the field converted to T at position (column) name. + /// + /// The of the field. + /// The named index of the field. + /// The field converted to T. + T? GetField(string name); + + /// + /// Gets the field converted to 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. + /// + /// + /// The named index of the field. + /// The zero based index of the instance of the field. + /// + T? GetField(string name, int index); + + /// + /// Gets the field converted to T at position (column) index using + /// the given . + /// + /// The of the field. + /// The zero based index of the field. + /// The used to convert the field to T. + /// The field converted to T. + T? GetField(int index, ITypeConverter converter); + + /// + /// Gets the field converted to T at position (column) name using + /// the given . + /// + /// The of the field. + /// The named index of the field. + /// The used to convert the field to T. + /// The field converted to T. + T? GetField(string name, ITypeConverter converter); + + /// + /// Gets the field converted to 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. + /// + /// The of the field. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The used to convert the field to T. + /// The field converted to T. + T? GetField(string name, int index, ITypeConverter converter); + + /// + /// Gets the field converted to T at position (column) index using + /// the given . + /// + /// The of the field. + /// The used to convert the field to T. + /// The zero based index of the field. + /// The field converted to T. + T? GetField(int index) where TConverter : ITypeConverter; + + /// + /// Gets the field converted to T at position (column) name using + /// the given . + /// + /// The of the field. + /// The used to convert the field to T. + /// The named index of the field. + /// The field converted to T. + T? GetField(string name) where TConverter : ITypeConverter; + + /// + /// Gets the field converted to 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. + /// + /// The of the field. + /// The used to convert the field to T. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The field converted to T. + T? GetField(string name, int index) where TConverter : ITypeConverter; + + /// + /// Gets the field converted to T at position (column) index. + /// + /// The of the field. + /// The zero based index of the field. + /// The field converted to type T. + /// A value indicating if the get was successful. + bool TryGetField(Type type, int index, out object? field); + + /// + /// Gets the field converted to T at position (column) name. + /// + /// The of the field. + /// The named index of the field. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(Type type, string name, out object? field); + + /// + /// Gets the field converted to 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. + /// + /// The of the field. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(Type type, string name, int index, out object? field); + + /// + /// Gets the field converted to T at position (column) index + /// using the specified . + /// + /// The of the field. + /// The zero based index of the field. + /// The used to convert the field to T. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(Type type, int index, ITypeConverter converter, out object? field); + + /// + /// Gets the field converted to T at position (column) name + /// using the specified . + /// + /// The of the field. + /// The named index of the field. + /// The used to convert the field to T. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(Type type, string name, ITypeConverter converter, out object? field); + + /// + /// Gets the field converted to T at position (column) name + /// using the specified . + /// + /// The of the field. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The used to convert the field to T. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(Type type, string name, int index, ITypeConverter converter, out object? field); + + /// + /// Gets the field converted to T at position (column) index. + /// + /// The of the field. + /// The zero based index of the field. + /// The field converted to type T. + /// A value indicating if the get was successful. + bool TryGetField(int index, out T? field); + + /// + /// Gets the field converted to T at position (column) name. + /// + /// The of the field. + /// The named index of the field. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(string name, out T? field); + + /// + /// Gets the field converted to 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. + /// + /// + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(string name, int index, out T? field); + + /// + /// Gets the field converted to T at position (column) index + /// using the specified . + /// + /// The of the field. + /// The zero based index of the field. + /// The used to convert the field to T. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(int index, ITypeConverter converter, out T? field); + + /// + /// Gets the field converted to T at position (column) name + /// using the specified . + /// + /// The of the field. + /// The named index of the field. + /// The used to convert the field to T. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(string name, ITypeConverter converter, out T? field); + + /// + /// Gets the field converted to T at position (column) name + /// using the specified . + /// + /// The of the field. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The used to convert the field to T. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(string name, int index, ITypeConverter converter, out T? field); + + /// + /// Gets the field converted to T at position (column) index + /// using the specified . + /// + /// The of the field. + /// The used to convert the field to T. + /// The zero based index of the field. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(int index, out T? field) where TConverter : ITypeConverter; + + /// + /// Gets the field converted to T at position (column) name + /// using the specified . + /// + /// The of the field. + /// The used to convert the field to T. + /// The named index of the field. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(string name, out T? field) where TConverter : ITypeConverter; + + /// + /// Gets the field converted to T at position (column) name + /// using the specified . + /// + /// The of the field. + /// The used to convert the field to T. + /// The named index of the field. + /// The zero based index of the instance of the field. + /// The field converted to T. + /// A value indicating if the get was successful. + bool TryGetField(string name, int index, out T? field) where TConverter : ITypeConverter; + + /// + /// Gets the record converted into T. + /// + /// The of the record. + /// The record converted to T. + T? GetRecord(); + + /// + /// Get the record converted into T. + /// + /// The of the record. + /// The anonymous type definition to use for the record. + /// The record converted to T. + T? GetRecord(T anonymousTypeDefinition); + + /// + /// Gets the record. + /// + /// The of the record. + /// The record. + 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 +{ + /// + /// Defines methods used to write to a CSV file. + /// + public interface IWriter : IWriterRow, IDisposable +#if !NET45 && !NET47 && !NETSTANDARD2_0 + , IAsyncDisposable +#endif + { + /// + /// Flushes the internal buffer to the then + /// flushes the . + /// + void Flush(); + + /// + /// Flushes the internal buffer to the then + /// flushes the . + /// + Task FlushAsync(); + + /// + /// Ends writing of the current record and starts a new record. + /// This flushes the buffer to the but + /// does not flush the . + /// + void NextRecord(); + + /// + /// Ends writing of the current record and starts a new record. + /// This flushes the buffer to the but + /// does not flush the . + /// + Task NextRecordAsync(); + + /// + /// Writes the list of records to the CSV file. + /// + /// The records to write. + void WriteRecords(IEnumerable records); + + /// + /// Writes the list of records to the CSV file. + /// + /// Record type. + /// The records to write. + void WriteRecords(IEnumerable records); + + /// + /// Writes the list of records to the CSV file. + /// + /// The records to write. + /// The cancellation token to stop the writing. + Task WriteRecordsAsync(IEnumerable records, CancellationToken cancellationToken = default); + + /// + /// Writes the list of records to the CSV file. + /// + /// Record type. + /// The records to write. + /// The cancellation token to stop the writing. + Task WriteRecordsAsync(IEnumerable records, CancellationToken cancellationToken = default); + +#if !NET45 + /// + /// Writes the list of records to the CSV file. + /// + /// Record type. + /// The records to write. + /// The cancellation token to stop the writing. + Task WriteRecordsAsync(IAsyncEnumerable 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 +{ + /// + /// Defines methods used to write a CSV row. + /// + public interface IWriterRow + { + /// + /// The header record. + /// + string[] HeaderRecord { get; } + + /// + /// The current row. + /// + int Row { get; } + + /// + /// The current field index. + /// + int Index { get; } + + /// + /// Gets the writing context. + /// + CsvContext Context { get; } + + /// + /// Gets or sets the configuration. + /// + IWriterConfiguration Configuration { get; } + + /// + /// Writes a field that has already been converted to a + /// from an . + /// 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. + /// + /// The converted field to write. + /// The type of the field before it was converted into a string. + void WriteConvertedField(string field, Type fieldType); + + /// + /// Writes the field to the CSV file. The field + /// may get quotes added to it. + /// When all fields are written for a record, + /// must be called + /// to complete writing of the current record. + /// + /// The field to write. + void WriteField(string field); + + /// + /// Writes the field to the CSV file. This will + /// ignore any need to quote and ignore + /// + /// and just quote based on the shouldQuote + /// parameter. + /// When all fields are written for a record, + /// must be called + /// to complete writing of the current record. + /// + /// The field to write. + /// True to quote the field, otherwise false. + void WriteField(string field, bool shouldQuote); + + /// + /// Writes the field to the CSV file. + /// When all fields are written for a record, + /// must be called + /// to complete writing of the current record. + /// + /// The type of the field. + /// The field to write. + void WriteField(T field); + + /// + /// Writes the field to the CSV file. + /// When all fields are written for a record, + /// must be called + /// to complete writing of the current record. + /// + /// The type of the field. + /// The field to write. + /// The converter used to convert the field into a string. + void WriteField(T field, ITypeConverter converter); + + /// + /// Writes the field to the CSV file + /// using the given . + /// When all fields are written for a record, + /// must be called + /// to complete writing of the current record. + /// + /// The type of the field. + /// The type of the converter. + /// The field to write. + void WriteField(T field); + + /// + /// Writes a comment. + /// + /// The comment to write. + void WriteComment(string comment); + + /// + /// Writes the header record from the given members. + /// + /// The type of the record. + void WriteHeader(); + + /// + /// Writes the header record from the given members. + /// + /// The type of the record. + void WriteHeader(Type type); + + /// + /// Writes the record to the CSV file. + /// + /// The type of the record. + /// The record to write. + void WriteRecord(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 Binary files /dev/null and b/ThirdParty/CsvHelper-master/src/CsvHelper/Icon.png 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 +{ + /// + /// Invalid header information. + /// + public class InvalidHeader + { + /// + /// Header names mapped to a CSV field that couldn't be found. + /// + public List Names { get; set; } = new List(); + + /// + /// Header name index maped to a CSV field that couldn't be found. + /// + 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(this LinkedList list, LinkedListNode? 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 +{ + /// + /// Represents an error due to a field that is too large. + /// + [Serializable] + public class MaxFieldSizeException : CsvHelperException + { + /// + /// Initializes a new instance of the class. + /// + /// The reading context. + public MaxFieldSizeException(CsvContext context) : base(context) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The reading context. + /// The message that describes the error. + public MaxFieldSizeException(CsvContext context, string message) : base(context, message) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The reading context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public 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 +{ + /// + /// Represents an error caused because a field is missing + /// in the header while reading a CSV file. + /// + [Serializable] + public class MissingFieldException : ReaderException + { + /// + /// Initializes a new instance of the class. + /// + /// The reading context. + public MissingFieldException(CsvContext context) : base(context) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The reading context. + /// The message that describes the error. + public MissingFieldException(CsvContext context, string message) : base(context, message) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The reading context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public MissingFieldException(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 +{ + /// + /// Efficiently creates instances of object types. + /// + public class ObjectCreator + { + private readonly Dictionary> cache = new Dictionary>(); + + /// + /// Creates an instance of type T using the given arguments. + /// + /// The type to create an instance of. + /// The constrcutor arguments. + public T CreateInstance(params object[] args) + { + return (T)CreateInstance(typeof(T), args); + } + + /// + /// Creates an instance of the given type using the given arguments. + /// + /// The type to create an instance of. + /// The constructor arguments. + public object CreateInstance(Type type, params object[] args) + { + var func = GetFunc(type, args); + + return func(args); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Func 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 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(); + 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>(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(); + 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 +{ + /// + /// Creates objects from a given type. + /// + public class ObjectResolver : IObjectResolver + { + private static IObjectResolver current; + private readonly ObjectCreator objectCreator = new ObjectCreator(); + + /// + /// Gets or sets the current resolver. + /// Use an instance of this instead if at all possible. + /// + public static IObjectResolver Current + { + get + { + return current; + } + set + { + if (value == null) + { + throw new InvalidOperationException($"{nameof(IObjectResolver)} cannot be null."); + } + + current = value; + } + } + + /// + /// A value indicating if the resolver's + /// returns false that an object will still be created using + /// CsvHelper's object creation. True to fallback, otherwise false. + /// Default value is true. + /// + public bool UseFallback { get; private set; } + + /// + /// 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. + /// + public Func CanResolve { get; private set; } + + /// + /// The function that creates an object from a given type. + /// + public Func 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); + } + }); + } + + /// + /// Creates an instance of the object resolver using default values. + /// + public ObjectResolver() + { + CanResolve = type => true; + ResolveFunction = ResolveWithObjectCreator; + UseFallback = true; + } + + /// + /// Creates an instance of the object resolver using the given can create function + /// and create function. + /// + /// 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. + /// The function that creates an object from a given type. + /// A value indicating if the resolver's + /// returns false that an object will still be created using + /// CsvHelper's object creation. True to fallback, otherwise false. + /// Default value is true. + public ObjectResolver(Func canResolve, Func resolveFunction, bool useFallback = true) + { + CanResolve = canResolve ?? throw new ArgumentNullException(nameof(canResolve)); + ResolveFunction = resolveFunction ?? throw new ArgumentNullException(nameof(resolveFunction)); + UseFallback = useFallback; + } + + /// + /// Creates an object from the given type using the + /// function. If is false, the object will be + /// created using CsvHelper's default object creation. If + /// is false, an exception is thrown. + /// + /// The type to create an instance from. The created object + /// may not be the same type as the given type. + /// Constructor arguments used to create the type. + 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."); + } + + /// + /// Creates an object from the given type using the + /// function. If is false, the object will be + /// created using CsvHelper's default object creation. If + /// is false, an exception is thrown. + /// + /// The type to create an instance from. The created object + /// may not be the same type as the given type. + /// Constructor arguments used to create the type. + public T Resolve(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 +{ + /// + /// Represents errors that occur while parsing a CSV file. + /// + [Serializable] + public class ParserException : CsvHelperException + { + /// + /// Initializes a new instance of the class. + /// + /// The reading context. + public ParserException(CsvContext context) : base(context) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The reading context. + /// The message that describes the error. + public ParserException(CsvContext context, string message) : base(context, message) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The reading context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ParserException(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 +{ + /// + /// Represents errors that occur while reading a CSV file. + /// + [Serializable] + public class ReaderException : CsvHelperException + { + /// + /// Initializes a new instance of the class. + /// + /// The reading context. + public ReaderException(CsvContext context) : base(context) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The reading context. + /// The message that describes the error. + public ReaderException(CsvContext context, string message) : base(context, message) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The reading context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ReaderException(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 +{ + /// + /// Extensions to help with reflection. + /// + public static class ReflectionExtensions + { + /// + /// Gets the type from the member. + /// + /// The member to get the type from. + /// The type. + [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."); + } + + /// + /// Gets a member expression for the member. + /// + /// The member to get the expression for. + /// The member expression. + /// The member expression. + [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."); + } + + /// + /// Gets a value indicating if the given type is anonymous. + /// True for anonymous, otherwise false. + /// + /// The type. + [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; + } + + /// + /// Gets a value indicating if the given type has a parameterless constructor. + /// True if it has a parameterless constructor, otherwise false. + /// + /// The type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool HasParameterlessConstructor(this Type type) + { + return type.GetConstructor(new Type[0]) != null; + } + + /// + /// Gets a value indicating if the given type has any constructors. + /// + /// The type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool HasConstructor(this Type type) + { + return type.GetConstructors().Length > 0; + } + + /// + /// Gets the constructor that contains the most parameters. + /// + /// The type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ConstructorInfo GetConstructorWithMostParameters(this Type type) + { + return type.GetConstructors() + .OrderByDescending(c => c.GetParameters().Length) + .First(); + } + + /// + /// Gets a value indicating if the type is a user defined struct. + /// True if it is a user defined struct, otherwise false. + /// + /// The type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsUserDefinedStruct(this Type type) + { + return type.IsValueType && !type.IsPrimitive && !type.IsEnum; + } + + /// + /// Gets a string representation of the constructor. + /// + /// The constructor. + [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; + } + + /// + /// Gets a string representation of the parameter. + /// + /// The parameter. + [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 +{ + /// + /// Common reflection tasks. + /// + internal static class ReflectionHelper + { + /// + /// Gets the from the type where the property was declared. + /// + /// The type the property belongs to. + /// The property to search. + /// Flags for how the property is retrieved. + [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; + } + + /// + /// Gets the from the type where the field was declared. + /// + /// The type the field belongs to. + /// The field to search. + /// Flags for how the field is retrieved. + [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; + } + + /// + /// 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. + /// + /// The to get properties for. + /// The flags for getting the properties. + /// If true, parent class properties that are hidden by `new` child properties will be overwritten. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static List GetUniqueProperties(Type type, BindingFlags flags, bool overwrite = false) + { + var ignoreBase = type.GetCustomAttribute(typeof(IgnoreBaseAttribute)) != null; + + var properties = new Dictionary(); + + 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(); + } + + /// + /// 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. + /// + /// The to get fields for. + /// The flags for getting the fields. + /// If true, parent class fields that are hidden by `new` child fields will be overwritten. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static List GetUniqueFields(Type type, BindingFlags flags, bool overwrite = false) + { + var ignoreBase = type.GetCustomAttribute(typeof(IgnoreBaseAttribute)) != null; + + var fields = new Dictionary(); + + 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(); + } + + /// + /// Gets the property from the expression. + /// + /// The type of the model. + /// The type of the property. + /// The expression. + /// The for the expression. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MemberInfo GetMember(Expression> 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."); + } + + /// + /// Gets the member inheritance chain as a stack. + /// + /// The type of the model. + /// The type of the property. + /// The member expression. + /// The inheritance chain for the given member expression as a stack. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Stack GetMembers(Expression> expression) + { + var stack = new Stack(); + + 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 +{ + /// + /// Converts an to and from a . + /// + public class ArrayConverter : IEnumerableConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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(); + 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 +{ + /// + /// Converts a to and from a . + /// + public class BigIntegerConverter : DefaultTypeConverter + { + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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); + } + + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class BooleanConverter : DefaultTypeConverter + { + /// + 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); + } + + /// + 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 +{ + /// + /// Converts a to and from a . + /// + public class ByteArrayConverter : DefaultTypeConverter + { + private readonly ByteArrayConverterOptions options; + private readonly string HexStringPrefix; + private readonly byte ByteLength; + + /// + /// Creates a new ByteArrayConverter using the given . + /// + /// The options. + 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; + } + + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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); + } + + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Options for converting byte arrays. + /// + [Flags] + public enum ByteArrayConverterOptions + { + /// + /// No options. + /// + None = 0, + + // TypeOptions + + /// + /// Hexadecimal encoding. + /// + Hexadecimal = 1, + + /// + /// Base64 encoding. + /// + Base64 = 2, + + // HexFormattingOptions + + /// + /// Use dashes in between hex values. + /// + HexDashes = 4, + + /// + /// Prefix hex number with 0x. + /// + 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 +{ + /// + /// Converts a to and from a . + /// + public class ByteConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class CharConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + public class CollectionConverterFactory : ITypeConverterFactory + { + private int dictionaryTypeHashCode = typeof(IDictionary).GetHashCode(); + private List enumerableTypeHashCodes = new List + { + typeof(IList).GetHashCode(), + typeof(ICollection).GetHashCode(), + typeof(IEnumerable).GetHashCode(), + }; + + /// + 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; + } + + /// + 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 +{ + /// + /// Converts a to and from a . + /// + public class CollectionGenericConverter : IEnumerableConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class DateOnlyConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class DateTimeConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class DateTimeOffsetConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class DecimalConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts an to and from a . + /// + public class DefaultTypeConverter : ITypeConverter + { + /// + 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); + } + + /// + 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 +{ + /// + /// Converts a to and from a . + /// + public class DoubleConverter : DefaultTypeConverter + { + private Lazy defaultFormat = new Lazy(() => double.TryParse(double.MaxValue.ToString("R"), out var _) ? "R" : "G17"); + + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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); + } + + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts an to and from a . + /// + public class EnumConverter : DefaultTypeConverter + { + private readonly Type type; + private readonly Dictionary enumNamesByAttributeNames = new Dictionary(); + private readonly Dictionary enumNamesByAttributeNamesIgnoreCase = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary attributeNamesByEnumValues = new Dictionary(); + + // enumNamesByAttributeNames + // enumNamesByAttributeNamesIgnoreCase + // [Name("Foo")]:One + + // attributeNamesByEnumValues + // 1:[Name("Foo")] + + /// + /// Creates a new for the given . + /// + /// The type of the Enum. + 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(); + 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); + } + } + } + } + } + + /// + 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 + } + + /// + 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 +{ + /// + public class EnumConverterFactory : ITypeConverterFactory + { + /// + public bool CanCreate(Type type) + { + return typeof(Enum).IsAssignableFrom(type); + } + + /// + 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(); + + 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 +{ + /// + /// Throws an exception when used. This is here so that it's apparent + /// that there is no support for type conversion. A custom + /// converter will need to be created to have a field convert to and + /// from an IEnumerable. + /// + public class EnumerableConverter : DefaultTypeConverter + { + /// + /// Throws an exception. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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); + } + + /// + /// Throws an exception. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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 +{ + /// + /// Converts a to and from a . + /// + public class GuidConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts an to and from a . + /// + public class IDictionaryConverter : DefaultTypeConverter + { + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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; + } + + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData) + { + var dictionary = new Dictionary(); + + 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 +{ + /// + /// Converts an to and from a . + /// + public class IDictionaryGenericConverter : IDictionaryConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts an to and from a . + /// + public class IEnumerableConverter : DefaultTypeConverter + { + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// + /// + /// The string representation of the object. + 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; + } + + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData) + { + var list = new List(); + + 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 +{ + /// + /// Converts an to and from a . + /// + public class IEnumerableGenericConverter : IEnumerableConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts objects to and from strings. + /// + public interface ITypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData); + + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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 +{ + /// + /// Produces for the specified + /// + public interface ITypeConverterFactory + { + /// + /// Determines if the factory can create a type converter for the given type. + /// + /// The to be checked + /// true if the factory can create the type, otherwise false. + bool CanCreate(Type type); + + /// + /// Creates a type converter for the given type and assigns it to the given out typeConverter parameter. + /// + /// The type to create the converter for. + /// The type converter cache. + /// The parameter to set the converter to. + /// true if the converter should be added to the cache, otherwise false. + 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 +{ + /// + /// Converts a to and from a . + /// + public class Int16Converter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts an to and from a . + /// + public class Int32Converter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts an to and from a . + /// + public class Int64Converter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class NullableConverter : DefaultTypeConverter + { + /// + /// Gets the type of the nullable. + /// + /// + /// The type of the nullable. + /// + public Type NullableType { get; private set; } + + /// + /// Gets the underlying type of the nullable. + /// + /// + /// The underlying type. + /// + public Type UnderlyingType { get; private set; } + + /// + /// Gets the type converter for the underlying type. + /// + /// + /// The type converter. + /// + public ITypeConverter UnderlyingTypeConverter { get; private set; } + + /// + /// Creates a new for the given . + /// + /// The nullable type. + /// The type converter factory. + /// type is not a nullable type. + 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); + } + + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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); + } + + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// + /// + /// The string representation of the object. + 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 +{ + /// + public class NullableConverterFactory : ITypeConverterFactory + { + /// + public bool CanCreate(Type type) + { + return (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>))); + } + + /// + 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 +{ + /// + /// Converts a to and from a . + /// + public class SByteConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class SingleConverter : DefaultTypeConverter + { + private Lazy defaultFormat = new Lazy(() => float.TryParse(float.MaxValue.ToString("R"), out var _) ? "R" : "G9"); + + /// + /// Converts the object to a string. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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); + } + + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class StringConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class TimeOnlyConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class TimeSpanConverter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Throws an exception when used. This is here so that it's apparent + /// that there is no support for type conversion. A custom + /// converter will need to be created to have a field convert to and + /// from . + /// + public class TypeConverter : DefaultTypeConverter + { + /// + /// Throws an exception. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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); + } + + /// + /// Throws an exception. + /// + /// The object to convert to a string. + /// The for the current record. + /// The for the member being written. + /// The string representation of the object. + 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 +{ + /// + /// Caches s for a given type. + /// + public class TypeConverterCache + { + private readonly Dictionary typeConverters = new Dictionary(); + private readonly List typeConverterFactories = new List(); + private readonly Dictionary typeConverterFactoryCache = new Dictionary(); + + /// + /// Initializes the class. + /// + public TypeConverterCache() + { + CreateDefaultConverters(); + } + + /// + /// Determines if there is a converter registered for the given type. + /// + /// The type to check. + /// true if the converter is registered, otherwise false. + public bool Contains(Type type) + { + return typeConverters.ContainsKey(type); + } + + /// + /// Adds the . + /// Factories are queried in order of being added and first factory that handles the type is used for creating the . + /// + /// Type converter factory + public void AddConverterFactory(ITypeConverterFactory typeConverterFactory) + { + if (typeConverterFactory == null) + { + throw new ArgumentNullException(nameof(typeConverterFactory)); + } + + typeConverterFactories.Add(typeConverterFactory); + } + + /// + /// Adds the for the given . + /// + /// The type the converter converts. + /// The type converter that converts the type. + 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; + } + + /// + /// Adds the for the given . + /// + /// The type the converter converts. + /// The type converter that converts the type. + public void AddConverter(ITypeConverter typeConverter) + { + if (typeConverter == null) + { + throw new ArgumentNullException(nameof(typeConverter)); + } + + typeConverters[typeof(T)] = typeConverter; + } + + /// + /// Adds the given to all registered types. + /// + /// The type converter. + public void AddConverter(ITypeConverter typeConverter) + { + foreach (var type in typeConverters.Keys) + { + typeConverters[type] = typeConverter; + } + } + + /// + /// Removes the for the given . + /// + /// The type to remove the converter for. + public void RemoveConverter(Type type) + { + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + + typeConverters.Remove(type); + } + + /// + /// Removes the for the given . + /// + /// The type to remove the converter for. + public void RemoveConverter() + { + RemoveConverter(typeof(T)); + } + + /// + /// Removes the ITypeConverterFactory. + /// + /// The ITypeConverterFactory to remove. + 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); + } + } + + /// + /// Gets the converter for the given . + /// + /// The type to get the converter for. + /// The for the given . + 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(); + } + + /// + /// 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. + /// + /// The member to get the converter for. + public ITypeConverter GetConverter(MemberInfo member) + { + var typeConverterAttribute = member.GetCustomAttribute(); + if (typeConverterAttribute != null) + { + return typeConverterAttribute.TypeConverter; + } + + return GetConverter(member.MemberType()); + } + + /// + /// Gets the converter for the given . + /// + /// The type to get the converter for. + /// The for the given . + public ITypeConverter GetConverter() + { + 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 +{ + /// + /// Represents errors that occur while reading a CSV file. + /// + [Serializable] + public class TypeConverterException : CsvHelperException + { + /// + /// The text used in ConvertFromString. + /// + public string Text { get; private set; } + + /// + /// The value used in ConvertToString. + /// + public object Value { get; private set; } + + /// + /// The type converter. + /// + public ITypeConverter TypeConverter { get; private set; } + + /// + /// The member map data used in ConvertFromString and ConvertToString. + /// + public MemberMapData MemberMapData { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The type converter. + /// The member map data. + /// The text. + /// The reading context. + public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, string text, CsvContext context) : base(context) + { + TypeConverter = typeConverter; + MemberMapData = memberMapData; + Text = text; + } + + /// + /// Initializes a new instance of the class. + /// + /// The type converter. + /// The member map data. + /// The value. + /// The writing context. + public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, object value, CsvContext context) : base(context) + { + TypeConverter = typeConverter; + MemberMapData = memberMapData; + Value = value; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The type converter. + /// The member map data. + /// The text. + /// The reading context. + /// The message that describes the error. + public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, string text, CsvContext context, string message) : base(context, message) + { + TypeConverter = typeConverter; + MemberMapData = memberMapData; + Text = text; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The type converter. + /// The member map data. + /// The value. + /// The writing context. + /// The message that describes the error. + public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, object value, CsvContext context, string message) : base(context, message) + { + TypeConverter = typeConverter; + MemberMapData = memberMapData; + Value = value; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The type converter. + /// The member map data. + /// The text. + /// The reading context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, string text, CsvContext context, string message, Exception innerException) : base(context, message, innerException) + { + TypeConverter = typeConverter; + MemberMapData = memberMapData; + Text = text; + } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The type converter. + /// The member map data. + /// The value. + /// The writing context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public TypeConverterException(ITypeConverter typeConverter, MemberMapData memberMapData, object value, 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 +{ + /// + /// Options used when doing type conversion. + /// + public class TypeConverterOptions + { + private static readonly string[] defaultBooleanTrueValues = { }; + private static readonly string[] defaultBooleanFalseValues = { }; + private static readonly string[] defaultNullValues = { }; + + /// + /// Gets or sets the culture info. + /// + public CultureInfo CultureInfo { get; set; } + + /// + /// Gets or sets the date time style. + /// + public DateTimeStyles? DateTimeStyle { get; set; } + + /// + /// Gets or sets the time span style. + /// + public TimeSpanStyles? TimeSpanStyle { get; set; } + + /// + /// Gets or sets the number style. + /// + public NumberStyles? NumberStyles { get; set; } + + /// + /// Gets or sets the string format. + /// + public string[] Formats { get; set; } + + /// + /// Gets or sets the . + /// + public UriKind? UriKind { get; set; } + + /// + /// Ingore case when parsing enums. Default is false. + /// + public bool? EnumIgnoreCase { get; set; } + + /// + /// Gets the list of values that can be + /// used to represent a boolean of true. + /// + public List BooleanTrueValues { get; } = new List(defaultBooleanTrueValues); + + /// + /// Gets the list of values that can be + /// used to represent a boolean of false. + /// + public List BooleanFalseValues { get; } = new List(defaultBooleanFalseValues); + + /// + /// Gets the list of values that can be used to represent a null value. + /// + public List NullValues { get; } = new List(defaultNullValues); + + /// + /// Merges TypeConverterOptions by applying the values of sources in order on to each other. + /// The first object is the source object. + /// + /// The sources that will be applied. + /// The updated source object. + 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 +{ + /// + /// Caches for a given type. + /// + public class TypeConverterOptionsCache + { + private Dictionary typeConverterOptions = new Dictionary(); + + /// + /// Adds the for the given . + /// + /// The type the options are for. + /// The options. + public void AddOptions(Type type, TypeConverterOptions options) + { + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + + typeConverterOptions[type] = options ?? throw new ArgumentNullException(nameof(options)); + } + + /// + /// Adds the for the given . + /// + /// The type the options are for. + /// The options. + public void AddOptions(TypeConverterOptions options) + { + AddOptions(typeof(T), options); + } + + /// + /// Adds the given to all registered types. + /// + /// + public void AddOptions(TypeConverterOptions options) + { + foreach (var type in typeConverterOptions.Keys) + { + typeConverterOptions[type] = options; + } + } + + /// + /// Removes the for the given type. + /// + /// The type to remove the options for. + public void RemoveOptions(Type type) + { + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + + typeConverterOptions.Remove(type); + } + + /// + /// Removes the for the given type. + /// + /// The type to remove the options for. + public void RemoveOptions() + { + RemoveOptions(typeof(T)); + } + + /// + /// Get the for the given . + /// + /// The type the options are for. + /// The options for the given type. + 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; + } + + /// + /// Get the for the given . + /// + /// The type the options are for. + /// The options for the given type. + public TypeConverterOptions GetOptions() + { + 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 +{ + /// + /// Converts a to and from a . + /// + public class UInt16Converter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class UInt32Converter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class UInt64Converter : DefaultTypeConverter + { + /// + /// Converts the string to an object. + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// The object created from the string. + 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 +{ + /// + /// Converts a to and from a . + /// + public class UriConverter : DefaultTypeConverter + { + /// + /// Converts the to a . + /// + /// The string to convert to an object. + /// The for the current record. + /// The for the member being created. + /// + /// The created from the string. + /// + 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 +{ + /// + /// Represents a user supplied validation failure. + /// + [Serializable] + public abstract class ValidationException : CsvHelperException + { + /// + /// Initializes a new instance of the class. + /// + /// The reading context. + public ValidationException(CsvContext context) : base(context) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The reading context. + /// The message that describes the error. + public ValidationException(CsvContext context, string message) : base(context, message) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The reading context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ValidationException(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 +{ + /// + /// Represents errors that occur while writing a CSV file. + /// + [Serializable] + public class WriterException : CsvHelperException + { + /// + /// Initializes a new instance of the class. + /// + /// The writing context. + public WriterException(CsvContext context) : base(context) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The writing context. + /// The message that describes the error. + public WriterException(CsvContext context, string message) : base(context, message) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that + /// is the cause of this exception. + /// + /// The writing context. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public WriterException(CsvContext context, string message, Exception innerException) : base(context, message, innerException) { } + } +} -- cgit v1.1-26-g67d0