diff --git a/.editorconfig b/.editorconfig
index 3098a35..6a67ed6 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,240 +1,240 @@
-# Удалите строку ниже, если вы хотите наследовать параметры .editorconfig из каталогов, расположенных выше в иерархии
-root = true
-
-# Файлы C#
-[*.cs]
-
-#### Основные параметры EditorConfig ####
-
-# Отступы и интервалы
-indent_size = 4
-indent_style = space
-tab_width = 4
-
-# Предпочтения для новых строк
-end_of_line = crlf
-insert_final_newline = false
-
-#### Рекомендации по написанию кода .NET ####
-
-# Упорядочение Using
-dotnet_separate_import_directive_groups = false
-dotnet_sort_system_directives_first = true
-file_header_template = unset
-
-# Предпочтения для this. и Me.
-dotnet_style_qualification_for_event = false
-dotnet_style_qualification_for_field = false
-dotnet_style_qualification_for_method = false
-dotnet_style_qualification_for_property = false
-
-# Параметры использования ключевых слов языка и типов BCL
-dotnet_style_predefined_type_for_locals_parameters_members = true
-dotnet_style_predefined_type_for_member_access = true
-
-# Предпочтения для скобок
-dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary
-dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
-dotnet_style_parentheses_in_other_operators = never_if_unnecessary
-dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
-
-# Предпочтения модификатора
-dotnet_style_require_accessibility_modifiers = for_non_interface_members
-
-# Выражения уровень предпочтения
-dotnet_style_coalesce_expression = true
-dotnet_style_collection_initializer = true
-dotnet_style_explicit_tuple_names = true
-dotnet_style_namespace_match_folder = true
-dotnet_style_null_propagation = true
-dotnet_style_object_initializer = true
-dotnet_style_operator_placement_when_wrapping = beginning_of_line
-dotnet_style_prefer_auto_properties = true:suggestion
-dotnet_style_prefer_compound_assignment = true
-dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
-dotnet_style_prefer_conditional_expression_over_return = true:suggestion
-dotnet_style_prefer_inferred_anonymous_type_member_names = true
-dotnet_style_prefer_inferred_tuple_names = true
-dotnet_style_prefer_is_null_check_over_reference_equality_method = true
-dotnet_style_prefer_simplified_boolean_expressions = true
-dotnet_style_prefer_simplified_interpolation = true
-
-# Предпочтения для полей
-dotnet_style_readonly_field = false:silent
-
-# Настройки параметров
-dotnet_code_quality_unused_parameters = non_public
-
-# Параметры подавления
-dotnet_remove_unnecessary_suppression_exclusions = none
-
-# Предпочтения для новых строк
-dotnet_style_allow_multiple_blank_lines_experimental = false
-dotnet_style_allow_statement_immediately_after_block_experimental = true
-
-#### Рекомендации по написанию кода C# ####
-
-# Предпочтения var
-csharp_style_var_elsewhere = true
-csharp_style_var_for_built_in_types = false
-csharp_style_var_when_type_is_apparent = true
-
-# Члены, заданные выражениями
-csharp_style_expression_bodied_accessors = true:suggestion
-csharp_style_expression_bodied_constructors = true:suggestion
-csharp_style_expression_bodied_indexers = true:suggestion
-csharp_style_expression_bodied_lambdas = true:suggestion
-csharp_style_expression_bodied_local_functions = true:suggestion
-csharp_style_expression_bodied_methods = true:suggestion
-csharp_style_expression_bodied_operators = true:suggestion
-csharp_style_expression_bodied_properties = true:suggestion
-
-# Настройки соответствия шаблонов
-csharp_style_pattern_matching_over_as_with_null_check = true
-csharp_style_pattern_matching_over_is_with_cast_check = true
-csharp_style_prefer_not_pattern = true
-csharp_style_prefer_pattern_matching = false
-csharp_style_prefer_switch_expression = false
-
-# Настройки проверки на null
-csharp_style_conditional_delegate_call = true
-
-# Предпочтения модификатора
-csharp_prefer_static_local_function = false:silent
-csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
-
-# Предпочтения для блоков кода
-csharp_prefer_braces = false:suggestion
-csharp_prefer_simple_using_statement = true
-csharp_style_namespace_declarations = file_scoped:suggestion
-
-# Выражения уровень предпочтения
-csharp_prefer_simple_default_expression = true:suggestion
-csharp_style_deconstructed_variable_declaration = false
-csharp_style_implicit_object_creation_when_type_is_apparent = true:silent
-csharp_style_inlined_variable_declaration = true
-csharp_style_pattern_local_over_anonymous_function = true
-csharp_style_prefer_index_operator = false:suggestion
-csharp_style_prefer_null_check_over_type_check = true:suggestion
-csharp_style_prefer_range_operator = false:suggestion
-csharp_style_throw_expression = true:suggestion
-csharp_style_unused_value_assignment_preference = discard_variable:warning
-csharp_style_unused_value_expression_statement_preference = unused_local_variable
-
-# предпочтения для директивы using
-csharp_using_directive_placement = outside_namespace
-
-# Предпочтения для новых строк
-csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
-csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
-csharp_style_allow_embedded_statements_on_same_line_experimental = true
-
-#### Правила форматирования C# ####
-
-# Предпочтения для новых строк
-csharp_new_line_before_catch = true
-csharp_new_line_before_else = true
-csharp_new_line_before_finally = true
-csharp_new_line_before_members_in_anonymous_types = true
-csharp_new_line_before_members_in_object_initializers = true
-csharp_new_line_before_open_brace = all
-csharp_new_line_between_query_expression_clauses = true
-
-# Предпочтения для отступов
-csharp_indent_block_contents = true
-csharp_indent_braces = false
-csharp_indent_case_contents = true
-csharp_indent_case_contents_when_block = true
-csharp_indent_labels = one_less_than_current
-csharp_indent_switch_labels = true
-
-# Предпочтения для интервалов
-csharp_space_after_cast = false
-csharp_space_after_colon_in_inheritance_clause = true
-csharp_space_after_comma = true
-csharp_space_after_dot = false
-csharp_space_after_keywords_in_control_flow_statements = true
-csharp_space_after_semicolon_in_for_statement = true
-csharp_space_around_binary_operators = before_and_after
-csharp_space_around_declaration_statements = false
-csharp_space_before_colon_in_inheritance_clause = true
-csharp_space_before_comma = false
-csharp_space_before_dot = false
-csharp_space_before_open_square_brackets = false
-csharp_space_before_semicolon_in_for_statement = false
-csharp_space_between_empty_square_brackets = false
-csharp_space_between_method_call_empty_parameter_list_parentheses = false
-csharp_space_between_method_call_name_and_opening_parenthesis = false
-csharp_space_between_method_call_parameter_list_parentheses = false
-csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
-csharp_space_between_method_declaration_name_and_open_parenthesis = false
-csharp_space_between_method_declaration_parameter_list_parentheses = false
-csharp_space_between_parentheses = false
-csharp_space_between_square_brackets = false
-
-# Предпочтения переноса
-csharp_preserve_single_line_blocks = true
-csharp_preserve_single_line_statements = true
-
-#### Стили именования ####
-
-# Правила именования
-
-dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
-dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
-dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
-
-dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
-dotnet_naming_rule.types_should_be_pascal_case.symbols = types
-dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
-
-dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
-dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
-dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
-
-# Спецификации символов
-
-dotnet_naming_symbols.interface.applicable_kinds = interface
-dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.interface.required_modifiers =
-
-dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
-dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.types.required_modifiers =
-
-dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
-dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.non_field_members.required_modifiers =
-
-# Стили именования
-
-dotnet_naming_style.pascal_case.required_prefix =
-dotnet_naming_style.pascal_case.required_suffix =
-dotnet_naming_style.pascal_case.word_separator =
-dotnet_naming_style.pascal_case.capitalization = pascal_case
-
-dotnet_naming_style.begins_with_i.required_prefix = I
-dotnet_naming_style.begins_with_i.required_suffix =
-dotnet_naming_style.begins_with_i.word_separator =
-dotnet_naming_style.begins_with_i.capitalization = pascal_case
-csharp_style_prefer_local_over_anonymous_function = true:suggestion
-
-[*.{cs,vb}]
-dotnet_style_operator_placement_when_wrapping = beginning_of_line
-tab_width = 4
-indent_size = 4
-dotnet_style_coalesce_expression = true:suggestion
-dotnet_style_null_propagation = true:suggestion
-dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
-dotnet_style_prefer_auto_properties = true:suggestion
-dotnet_style_object_initializer = true:suggestion
-dotnet_style_collection_initializer = true:suggestion
-dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
-dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
-dotnet_style_prefer_conditional_expression_over_return = true:suggestion
-dotnet_style_explicit_tuple_names = true:suggestion
-dotnet_style_prefer_inferred_tuple_names = true:suggestion
-dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
-dotnet_style_prefer_compound_assignment = true:suggestion
-dotnet_style_prefer_simplified_interpolation = true:suggestion
+# Удалите строку ниже, если вы хотите наследовать параметры .editorconfig из каталогов, расположенных выше в иерархии
+root = true
+
+# Файлы C#
+[*.cs]
+
+#### Основные параметры EditorConfig ####
+
+# Отступы и интервалы
+indent_size = 4
+indent_style = space
+tab_width = 4
+
+# Предпочтения для новых строк
+end_of_line = crlf
+insert_final_newline = false
+
+#### Рекомендации по написанию кода .NET ####
+
+# Упорядочение Using
+dotnet_separate_import_directive_groups = false
+dotnet_sort_system_directives_first = true
+file_header_template = unset
+
+# Предпочтения для this. и Me.
+dotnet_style_qualification_for_event = false
+dotnet_style_qualification_for_field = false
+dotnet_style_qualification_for_method = false
+dotnet_style_qualification_for_property = false
+
+# Параметры использования ключевых слов языка и типов BCL
+dotnet_style_predefined_type_for_locals_parameters_members = true
+dotnet_style_predefined_type_for_member_access = true
+
+# Предпочтения для скобок
+dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
+
+# Предпочтения модификатора
+dotnet_style_require_accessibility_modifiers = for_non_interface_members
+
+# Выражения уровень предпочтения
+dotnet_style_coalesce_expression = true
+dotnet_style_collection_initializer = true
+dotnet_style_explicit_tuple_names = true
+dotnet_style_namespace_match_folder = true
+dotnet_style_null_propagation = true
+dotnet_style_object_initializer = true
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_prefer_compound_assignment = true
+dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
+dotnet_style_prefer_conditional_expression_over_return = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true
+dotnet_style_prefer_inferred_tuple_names = true
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true
+dotnet_style_prefer_simplified_boolean_expressions = true
+dotnet_style_prefer_simplified_interpolation = true
+
+# Предпочтения для полей
+dotnet_style_readonly_field = false:silent
+
+# Настройки параметров
+dotnet_code_quality_unused_parameters = non_public
+
+# Параметры подавления
+dotnet_remove_unnecessary_suppression_exclusions = none
+
+# Предпочтения для новых строк
+dotnet_style_allow_multiple_blank_lines_experimental = false
+dotnet_style_allow_statement_immediately_after_block_experimental = true
+
+#### Рекомендации по написанию кода C# ####
+
+# Предпочтения var
+csharp_style_var_elsewhere = true
+csharp_style_var_for_built_in_types = false
+csharp_style_var_when_type_is_apparent = true
+
+# Члены, заданные выражениями
+csharp_style_expression_bodied_accessors = true:suggestion
+csharp_style_expression_bodied_constructors = true:suggestion
+csharp_style_expression_bodied_indexers = true:suggestion
+csharp_style_expression_bodied_lambdas = true:suggestion
+csharp_style_expression_bodied_local_functions = true:suggestion
+csharp_style_expression_bodied_methods = true:suggestion
+csharp_style_expression_bodied_operators = true:suggestion
+csharp_style_expression_bodied_properties = true:suggestion
+
+# Настройки соответствия шаблонов
+csharp_style_pattern_matching_over_as_with_null_check = true
+csharp_style_pattern_matching_over_is_with_cast_check = true
+csharp_style_prefer_not_pattern = true
+csharp_style_prefer_pattern_matching = false
+csharp_style_prefer_switch_expression = false
+
+# Настройки проверки на null
+csharp_style_conditional_delegate_call = true
+
+# Предпочтения модификатора
+csharp_prefer_static_local_function = false:silent
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
+
+# Предпочтения для блоков кода
+csharp_prefer_braces = false:suggestion
+csharp_prefer_simple_using_statement = true
+csharp_style_namespace_declarations = file_scoped:suggestion
+
+# Выражения уровень предпочтения
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_deconstructed_variable_declaration = false
+csharp_style_implicit_object_creation_when_type_is_apparent = true:silent
+csharp_style_inlined_variable_declaration = true
+csharp_style_pattern_local_over_anonymous_function = true
+csharp_style_prefer_index_operator = false:suggestion
+csharp_style_prefer_null_check_over_type_check = true:suggestion
+csharp_style_prefer_range_operator = false:suggestion
+csharp_style_throw_expression = true:suggestion
+csharp_style_unused_value_assignment_preference = discard_variable:warning
+csharp_style_unused_value_expression_statement_preference = unused_local_variable
+
+# предпочтения для директивы using
+csharp_using_directive_placement = outside_namespace
+
+# Предпочтения для новых строк
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
+csharp_style_allow_embedded_statements_on_same_line_experimental = true
+
+#### Правила форматирования C# ####
+
+# Предпочтения для новых строк
+csharp_new_line_before_catch = true
+csharp_new_line_before_else = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_open_brace = all
+csharp_new_line_between_query_expression_clauses = true
+
+# Предпочтения для отступов
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_case_contents_when_block = true
+csharp_indent_labels = one_less_than_current
+csharp_indent_switch_labels = true
+
+# Предпочтения для интервалов
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_between_square_brackets = false
+
+# Предпочтения переноса
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = true
+
+#### Стили именования ####
+
+# Правила именования
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Спецификации символов
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Стили именования
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+csharp_style_prefer_local_over_anonymous_function = true:suggestion
+
+[*.{cs,vb}]
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
+dotnet_style_prefer_conditional_expression_over_return = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:suggestion
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index ef8d169..9c9cd3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,359 +1,8 @@
-# User-specific files
-*.rsuser
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Ww][Ii][Nn]32/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
-[Bb]in/
-[Oo]bj/
-[Oo]ut/
-[Ll]og/
-[Ll]ogs/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-.vshistory/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUnit
-*.VisualState.xml
-TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# ASP.NET Scaffolding
-ScaffoldingReadMe.txt
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Coverlet is a free, cross platform Code Coverage Tool
-coverage*.json
-coverage*.xml
-coverage*.info
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
-
-# BeatPulse healthcheck temp database
-healthchecksdb
-
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
-
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
-
-# Fody - auto-generated XML schema
-FodyWeavers.xsd
\ No newline at end of file
+*.user
+[Bb]in/
+[Oo]bj/
+[Oo]ut/
+[Ll]og/
+[Ll]ogs/
+.vs/
+.vshistory/
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..cdc88bc
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,26 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // Use IntelliSense to find out which attributes exist for C# debugging
+ // Use hover for the description of the existing attributes
+ // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
+ "name": ".NET Core Launch (console)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ // If you have changed target frameworks, make sure to update the program path.
+ "program": "${workspaceFolder}/TestProgram/bin/Debug/net6.0/TestProgram.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/TestProgram",
+ // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..3fd6915
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,42 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/TestProgram/TestProgram.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/TestProgram/TestProgram.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "${workspaceFolder}/TestProgram/TestProgram.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/DTLib.sln b/DTLib.sln
index d072ac6..0784b85 100644
--- a/DTLib.sln
+++ b/DTLib.sln
@@ -1,38 +1,38 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.32014.148
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DTLib", "DTLib\DTLib.csproj", "{B620E5E9-800F-4B2D-B4A5-062E05DB704F}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProgram", "TestProgram\TestProgram.csproj", "{72BA37EF-07EC-4D34-966A-20D5E83ADB32}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6308F24E-A4FF-46B3-B72F-30E05DDCB1D5}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- .gitignore = .gitignore
- README.md = README.md
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Release|Any CPU.Build.0 = Release|Any CPU
- {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {6D0413D6-AF96-46C3-9E67-858AE2482818}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.32014.148
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DTLib", "DTLib\DTLib.csproj", "{B620E5E9-800F-4B2D-B4A5-062E05DB704F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProgram", "TestProgram\TestProgram.csproj", "{72BA37EF-07EC-4D34-966A-20D5E83ADB32}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6308F24E-A4FF-46B3-B72F-30E05DDCB1D5}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ .gitignore = .gitignore
+ README.md = README.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B620E5E9-800F-4B2D-B4A5-062E05DB704F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {72BA37EF-07EC-4D34-966A-20D5E83ADB32}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {6D0413D6-AF96-46C3-9E67-858AE2482818}
+ EndGlobalSection
+EndGlobal
diff --git a/DTLib/ColoredConsole.cs b/DTLib/ColoredConsole.cs
index 9c86dc9..ad55c8c 100644
--- a/DTLib/ColoredConsole.cs
+++ b/DTLib/ColoredConsole.cs
@@ -1,70 +1,70 @@
-namespace DTLib;
-
-//
-// вывод и ввод цветного текста в консоли
-// работает медленнее чем хотелось бы
-//
-public static class ColoredConsole
-{
- // парсит название цвета в ConsoleColor
- public static ConsoleColor ParseColor(string color) => color switch
- {
- //case "magneta":
- "m" => ConsoleColor.Magenta,
- //case "green":
- "g" => ConsoleColor.Green,
- //case "red":
- "r" => ConsoleColor.Red,
- //case "yellow":
- "y" => ConsoleColor.Yellow,
- //case "white":
- "w" => ConsoleColor.White,
- //case "blue":
- "b" => ConsoleColor.Blue,
- //case "cyan":
- "c" => ConsoleColor.Cyan,
- //case "h":
- "h" or "gray" => ConsoleColor.Gray,
- //case "black":
- "black" => ConsoleColor.Black,
- _ => throw new Exception($"ColoredConsole.ParseColor({color}) error: incorrect color"),
- };
-
- // вывод цветного текста
- public static void Write(params string[] input)
- {
- if (input.Length == 1)
- {
- if (Console.ForegroundColor != ConsoleColor.Gray)
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.Write(input[0]);
- }
- else if (input.Length % 2 == 0)
- {
- StringBuilder strB = new();
- for (ushort i = 0; i < input.Length; i++)
- {
- ConsoleColor c = ParseColor(input[i]);
- if (Console.ForegroundColor != c)
- {
- Console.Write(strB.ToString());
- Console.ForegroundColor = c;
- strB.Clear();
- }
- strB.Append(input[++i]);
- }
- if (strB.Length > 0)
- Console.Write(strB.ToString());
- }
- else throw new Exception("ColoredConsole.Write() error: every text string must have color string before");
- }
-
- // ввод цветного текста
- public static string Read(string color)
- {
- ConsoleColor c = ParseColor(color);
- if (Console.ForegroundColor != c)
- Console.ForegroundColor = c;
- return Console.ReadLine();
- }
-}
+namespace DTLib;
+
+//
+// вывод и ввод цветного текста в консоли
+// работает медленнее чем хотелось бы
+//
+public static class ColoredConsole
+{
+ // парсит название цвета в ConsoleColor
+ public static ConsoleColor ParseColor(string color) => color switch
+ {
+ //case "magneta":
+ "m" => ConsoleColor.Magenta,
+ //case "green":
+ "g" => ConsoleColor.Green,
+ //case "red":
+ "r" => ConsoleColor.Red,
+ //case "yellow":
+ "y" => ConsoleColor.Yellow,
+ //case "white":
+ "w" => ConsoleColor.White,
+ //case "blue":
+ "b" => ConsoleColor.Blue,
+ //case "cyan":
+ "c" => ConsoleColor.Cyan,
+ //case "h":
+ "h" or "gray" => ConsoleColor.Gray,
+ //case "black":
+ "black" => ConsoleColor.Black,
+ _ => throw new Exception($"ColoredConsole.ParseColor({color}) error: incorrect color"),
+ };
+
+ // вывод цветного текста
+ public static void Write(params string[] input)
+ {
+ if (input.Length == 1)
+ {
+ if (Console.ForegroundColor != ConsoleColor.Gray)
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Console.Write(input[0]);
+ }
+ else if (input.Length % 2 == 0)
+ {
+ StringBuilder strB = new();
+ for (ushort i = 0; i < input.Length; i++)
+ {
+ ConsoleColor c = ParseColor(input[i]);
+ if (Console.ForegroundColor != c)
+ {
+ Console.Write(strB.ToString());
+ Console.ForegroundColor = c;
+ strB.Clear();
+ }
+ strB.Append(input[++i]);
+ }
+ if (strB.Length > 0)
+ Console.Write(strB.ToString());
+ }
+ else throw new Exception("ColoredConsole.Write() error: every text string must have color string before");
+ }
+
+ // ввод цветного текста
+ public static string Read(string color)
+ {
+ ConsoleColor c = ParseColor(color);
+ if (Console.ForegroundColor != c)
+ Console.ForegroundColor = c;
+ return Console.ReadLine();
+ }
+}
diff --git a/DTLib/DTLib.csproj b/DTLib/DTLib.csproj
index 399646c..834c39f 100644
--- a/DTLib/DTLib.csproj
+++ b/DTLib/DTLib.csproj
@@ -1,20 +1,20 @@
-
-
- net6.0
- false
- disable
- portable
- DTLib
- True
- true
- False
-
-
-
-
-
-
-
-
-
-
+
+
+ net6.0
+ false
+ disable
+ portable
+ DTLib
+ True
+ true
+ False
+
+
+
+
+
+
+
+
+
+
diff --git a/DTLib/Dtsod/DtsodV21.cs b/DTLib/Dtsod/DtsodV21.cs
index d502f69..5541c38 100644
--- a/DTLib/Dtsod/DtsodV21.cs
+++ b/DTLib/Dtsod/DtsodV21.cs
@@ -1,327 +1,327 @@
-namespace DTLib.Dtsod;
-
-// v21
-// парсер теперь не может игнорировать комменты, потом починю
-// теперь числовые значения конвертируются в правильный тип, а не в int64/uint64 (новый вариант switch из c#9.0 делал какую-то дичь)
-// исправлены некоторые другие баги
-
-public class DtsodV21 : Dictionary, IDtsod
-{
- public DtsodVersion Version { get; } = DtsodVersion.V21;
-
- public IDictionary ToDictionary() => this;
-
- readonly string Text;
-
- //public Dictionary Values { get; set; }
- public DtsodV21(string text)
- {
- Text = text;
- foreach (KeyValuePair pair in Parse(text))
- Add(pair.Key, pair.Value);
- }
- public DtsodV21(IDictionary rawDict)
- {
- Text = "";
- foreach (KeyValuePair pair in rawDict)
- Add(pair.Key, pair.Value);
- }
-
-
- // выдаёт Exception
- public new dynamic this[string key]
- {
- get => TryGetValue(key, out dynamic value) ? value : throw new Exception($"Dtsod[{key}] key not found");
- set
- {
- if (!TrySetValue(key, value)) throw new Exception($"Dtsod[{key}] key not found");
- }
- }
-
- // не выдаёт KeyNotFoundException
- public new bool TryGetValue(string key, out dynamic value)
- {
- try
- {
- value = base[key];
- return true;
- }
- catch (KeyNotFoundException)
- {
- value = null;
- return false;
- }
- }
- public bool TrySetValue(string key, dynamic value)
- {
- try
- {
- base[key] = value;
- return true;
- }
- catch (KeyNotFoundException)
- {
- return false;
- }
- }
-
- public override string ToString() => Text;
-
- enum ValueType
- {
- List,
- Complex,
- String,
- Default
- }
-
- Dictionary Parse(string text)
- {
- Dictionary parsed = new();
- int i = 0;
- for (; i < text.Length; i++)
- ReadName();
- return parsed;
-
- // СЛОМАНО
- /*void ReadCommentLine()
- {
- for (; i < text.Length && text[i] != '\n'; i++) DebugNoTime("h", text[i].ToString());
- }*/
-
- void ReadName()
- {
-
- bool isListElem = false;
- dynamic value;
- StringBuilder defaultNameBuilder = new();
-
- for (; i < text.Length; i++)
- {
- switch (text[i])
- {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- break;
- case ':':
- i++;
- string name = defaultNameBuilder.ToString();
- value = ReadValue();
- // если value это null, эта строка выдавала ошибку
- //DebugNoTime("c", $"parsed.Add({name}, {value} { value.GetType() })");
- if (isListElem)
- {
- if (!parsed.ContainsKey(name))
- parsed.Add(name, new List());
- parsed[name].Add(value);
- }
- else
- parsed.Add(name, value);
- return;
- // строка, начинающаяся с # будет считаться комментом
- case '#':
- //ReadCommentLine();
- break;
- case '}':
- throw new Exception("Parse.ReadName() error: unexpected '}' at " + i + " char");
- // если $ перед названием параметра поставить, значение value добавится в лист с названием name
- case '$':
- if (defaultNameBuilder.ToString().Length != 0)
- throw new Exception("Parse.ReadName() error: unexpected '$' at " + i + " char");
- isListElem = true;
- break;
- case ';':
- throw new Exception("Parse.ReadName() error: unexpected ';' at " + i + " char");
- default:
- defaultNameBuilder.Append(text[i]);
- break;
- }
- }
- }
-
- dynamic ReadValue()
- {
- ValueType type = ValueType.Default;
- dynamic value = null;
-
- string ReadString()
- {
- i++;
- StringBuilder valueBuilder = new();
- valueBuilder.Append('"');
- for (; text[i] != '"' || text[i - 1] == '\\'; i++)
- {
- valueBuilder.Append(text[i]);
- }
- valueBuilder.Append('"');
- type = ValueType.String;
- return valueBuilder.ToString();
- }
-
- List ReadList()
- {
- i++;
- List output = new();
- StringBuilder valueBuilder = new();
- for (; text[i] != ']'; i++)
- {
- switch (text[i])
- {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- break;
- case ',':
- ParseValueToRightType(valueBuilder.ToString());
- output.Add(value);
- valueBuilder.Clear();
- break;
- default:
- valueBuilder.Append(text[i]);
- break;
- }
- }
- if (valueBuilder.Length > 0)
- {
- ParseValueToRightType(valueBuilder.ToString());
- output.Add(value);
- }
- type = ValueType.List;
- return output;
- }
-
- Dictionary ReadComplex()
- {
- StringBuilder valueBuilder = new();
- int balance = 1;
- i++;
- for (; balance != 0; i++)
- {
- switch (text[i])
- {
- case '"':
- valueBuilder.Append(ReadString());
- break;
- case '}':
- balance--;
- if (balance != 0)
- valueBuilder.Append(text[i]);
- break;
- case '{':
- balance++;
- valueBuilder.Append(text[i]);
- break;
- default:
- valueBuilder.Append(text[i]);
- break;
- }
- }
- i--; // i++ в for выполняется даже когда balance == 0, то есть text[i] получается == ;, что ломает всё
- type = ValueType.Complex;
- return Parse(valueBuilder.ToString());
- }
-
- void ParseValueToRightType(string stringValue)
- {
-
- switch (stringValue)
- {
-
- // bool
- case "true":
- case "false":
- value = stringValue.ToBool();
- break;
- // null
- case "null":
- value = null;
- break;
- default:
- if (stringValue.Contains('"'))
- value = stringValue.Remove(stringValue.Length - 1).Remove(0, 1);
- // double
- else if (stringValue.Contains('.'))
- value = stringValue.ToDouble();
- // ushort; ulong; uint
- else if (stringValue.Length > 2 && stringValue[stringValue.Length - 2] == 'u')
- {
- switch (stringValue[stringValue.Length - 1])
- {
- case 's':
- value = stringValue.Remove(stringValue.Length - 2).ToUShort();
- break;
- case 'i':
- value = stringValue.Remove(stringValue.Length - 2).ToUInt();
- break;
- case 'l':
- value = stringValue.Remove(stringValue.Length - 2).ToULong();
- break;
- default:
- throw new Exception($"Dtsod.Parse.ReadValue() error: value= wrong type ");
- };
- }
- // short; long; int
- else
- switch (stringValue[stringValue.Length - 1])
- {
- case 's':
- value = stringValue.Remove(stringValue.Length - 1).ToShort();
- break;
- case 'l':
- value = stringValue.Remove(stringValue.Length - 1).ToLong();
- break;
- default:
- value = stringValue.ToInt();
- break;
- }
- break;
- };
- }
-
- StringBuilder defaultValueBuilder = new();
- for (; i < text.Length; i++)
- {
- switch (text[i])
- {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- break;
- case '"':
- value = ReadString();
- break;
- case ';':
- switch (type)
- {
- case ValueType.String:
- ParseValueToRightType(value);
- break;
- case ValueType.Default:
- ParseValueToRightType(defaultValueBuilder.ToString());
- break;
- };
- return value;
- case '[':
- value = ReadList();
- break;
- case '{':
- value = ReadComplex();
- break;
- // строка, начинающаяся с # будет считаться комментом
- case '#':
- //ReadCommentLine();
- break;
- default:
- defaultValueBuilder.Append(text[i]);
- break;
- }
- }
- throw new Exception("Dtsod.Parse.ReadValue error: wtf it's the end of function");
- }
- }
-}
-
+namespace DTLib.Dtsod;
+
+// v21
+// парсер теперь не может игнорировать комменты, потом починю
+// теперь числовые значения конвертируются в правильный тип, а не в int64/uint64 (новый вариант switch из c#9.0 делал какую-то дичь)
+// исправлены некоторые другие баги
+
+public class DtsodV21 : Dictionary, IDtsod
+{
+ public DtsodVersion Version { get; } = DtsodVersion.V21;
+
+ public IDictionary ToDictionary() => this;
+
+ readonly string Text;
+
+ //public Dictionary Values { get; set; }
+ public DtsodV21(string text)
+ {
+ Text = text;
+ foreach (KeyValuePair pair in Parse(text))
+ Add(pair.Key, pair.Value);
+ }
+ public DtsodV21(IDictionary rawDict)
+ {
+ Text = "";
+ foreach (KeyValuePair pair in rawDict)
+ Add(pair.Key, pair.Value);
+ }
+
+
+ // выдаёт Exception
+ public new dynamic this[string key]
+ {
+ get => TryGetValue(key, out dynamic value) ? value : throw new Exception($"Dtsod[{key}] key not found");
+ set
+ {
+ if (!TrySetValue(key, value)) throw new Exception($"Dtsod[{key}] key not found");
+ }
+ }
+
+ // не выдаёт KeyNotFoundException
+ public new bool TryGetValue(string key, out dynamic value)
+ {
+ try
+ {
+ value = base[key];
+ return true;
+ }
+ catch (KeyNotFoundException)
+ {
+ value = null;
+ return false;
+ }
+ }
+ public bool TrySetValue(string key, dynamic value)
+ {
+ try
+ {
+ base[key] = value;
+ return true;
+ }
+ catch (KeyNotFoundException)
+ {
+ return false;
+ }
+ }
+
+ public override string ToString() => Text;
+
+ enum ValueType
+ {
+ List,
+ Complex,
+ String,
+ Default
+ }
+
+ Dictionary Parse(string text)
+ {
+ Dictionary parsed = new();
+ int i = 0;
+ for (; i < text.Length; i++)
+ ReadName();
+ return parsed;
+
+ // СЛОМАНО
+ /*void ReadCommentLine()
+ {
+ for (; i < text.Length && text[i] != '\n'; i++) DebugNoTime("h", text[i].ToString());
+ }*/
+
+ void ReadName()
+ {
+
+ bool isListElem = false;
+ dynamic value;
+ StringBuilder defaultNameBuilder = new();
+
+ for (; i < text.Length; i++)
+ {
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case ':':
+ i++;
+ string name = defaultNameBuilder.ToString();
+ value = ReadValue();
+ // если value это null, эта строка выдавала ошибку
+ //DebugNoTime("c", $"parsed.Add({name}, {value} { value.GetType() })");
+ if (isListElem)
+ {
+ if (!parsed.ContainsKey(name))
+ parsed.Add(name, new List());
+ parsed[name].Add(value);
+ }
+ else
+ parsed.Add(name, value);
+ return;
+ // строка, начинающаяся с # будет считаться комментом
+ case '#':
+ //ReadCommentLine();
+ break;
+ case '}':
+ throw new Exception("Parse.ReadName() error: unexpected '}' at " + i + " char");
+ // если $ перед названием параметра поставить, значение value добавится в лист с названием name
+ case '$':
+ if (defaultNameBuilder.ToString().Length != 0)
+ throw new Exception("Parse.ReadName() error: unexpected '$' at " + i + " char");
+ isListElem = true;
+ break;
+ case ';':
+ throw new Exception("Parse.ReadName() error: unexpected ';' at " + i + " char");
+ default:
+ defaultNameBuilder.Append(text[i]);
+ break;
+ }
+ }
+ }
+
+ dynamic ReadValue()
+ {
+ ValueType type = ValueType.Default;
+ dynamic value = null;
+
+ string ReadString()
+ {
+ i++;
+ StringBuilder valueBuilder = new();
+ valueBuilder.Append('"');
+ for (; text[i] != '"' || text[i - 1] == '\\'; i++)
+ {
+ valueBuilder.Append(text[i]);
+ }
+ valueBuilder.Append('"');
+ type = ValueType.String;
+ return valueBuilder.ToString();
+ }
+
+ List ReadList()
+ {
+ i++;
+ List output = new();
+ StringBuilder valueBuilder = new();
+ for (; text[i] != ']'; i++)
+ {
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case ',':
+ ParseValueToRightType(valueBuilder.ToString());
+ output.Add(value);
+ valueBuilder.Clear();
+ break;
+ default:
+ valueBuilder.Append(text[i]);
+ break;
+ }
+ }
+ if (valueBuilder.Length > 0)
+ {
+ ParseValueToRightType(valueBuilder.ToString());
+ output.Add(value);
+ }
+ type = ValueType.List;
+ return output;
+ }
+
+ Dictionary ReadComplex()
+ {
+ StringBuilder valueBuilder = new();
+ int balance = 1;
+ i++;
+ for (; balance != 0; i++)
+ {
+ switch (text[i])
+ {
+ case '"':
+ valueBuilder.Append(ReadString());
+ break;
+ case '}':
+ balance--;
+ if (balance != 0)
+ valueBuilder.Append(text[i]);
+ break;
+ case '{':
+ balance++;
+ valueBuilder.Append(text[i]);
+ break;
+ default:
+ valueBuilder.Append(text[i]);
+ break;
+ }
+ }
+ i--; // i++ в for выполняется даже когда balance == 0, то есть text[i] получается == ;, что ломает всё
+ type = ValueType.Complex;
+ return Parse(valueBuilder.ToString());
+ }
+
+ void ParseValueToRightType(string stringValue)
+ {
+
+ switch (stringValue)
+ {
+
+ // bool
+ case "true":
+ case "false":
+ value = stringValue.ToBool();
+ break;
+ // null
+ case "null":
+ value = null;
+ break;
+ default:
+ if (stringValue.Contains('"'))
+ value = stringValue.Remove(stringValue.Length - 1).Remove(0, 1);
+ // double
+ else if (stringValue.Contains('.'))
+ value = stringValue.ToDouble();
+ // ushort; ulong; uint
+ else if (stringValue.Length > 2 && stringValue[stringValue.Length - 2] == 'u')
+ {
+ switch (stringValue[stringValue.Length - 1])
+ {
+ case 's':
+ value = stringValue.Remove(stringValue.Length - 2).ToUShort();
+ break;
+ case 'i':
+ value = stringValue.Remove(stringValue.Length - 2).ToUInt();
+ break;
+ case 'l':
+ value = stringValue.Remove(stringValue.Length - 2).ToULong();
+ break;
+ default:
+ throw new Exception($"Dtsod.Parse.ReadValue() error: value= wrong type ");
+ };
+ }
+ // short; long; int
+ else
+ switch (stringValue[stringValue.Length - 1])
+ {
+ case 's':
+ value = stringValue.Remove(stringValue.Length - 1).ToShort();
+ break;
+ case 'l':
+ value = stringValue.Remove(stringValue.Length - 1).ToLong();
+ break;
+ default:
+ value = stringValue.ToInt();
+ break;
+ }
+ break;
+ };
+ }
+
+ StringBuilder defaultValueBuilder = new();
+ for (; i < text.Length; i++)
+ {
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case '"':
+ value = ReadString();
+ break;
+ case ';':
+ switch (type)
+ {
+ case ValueType.String:
+ ParseValueToRightType(value);
+ break;
+ case ValueType.Default:
+ ParseValueToRightType(defaultValueBuilder.ToString());
+ break;
+ };
+ return value;
+ case '[':
+ value = ReadList();
+ break;
+ case '{':
+ value = ReadComplex();
+ break;
+ // строка, начинающаяся с # будет считаться комментом
+ case '#':
+ //ReadCommentLine();
+ break;
+ default:
+ defaultValueBuilder.Append(text[i]);
+ break;
+ }
+ }
+ throw new Exception("Dtsod.Parse.ReadValue error: wtf it's the end of function");
+ }
+ }
+}
+
diff --git a/DTLib/Dtsod/DtsodV22.cs b/DTLib/Dtsod/DtsodV22.cs
index 64edd22..615f4a1 100644
--- a/DTLib/Dtsod/DtsodV22.cs
+++ b/DTLib/Dtsod/DtsodV22.cs
@@ -1,445 +1,445 @@
-namespace DTLib.Dtsod;
-
-// v22
-// метод ToString() теперь деконструирует объект в текст, а не возвращает параметр text из конструктора
-// деконструкция листов не работает из-за костыльного определения типов данных
-
-public class DtsodV22 : Dictionary, IDtsod
-{
- public DtsodVersion Version { get; } = DtsodVersion.V22;
-
- public IDictionary ToDictionary()
- {
- Dictionary newdict = new();
- foreach (KeyValuePair pair in this)
- newdict.Add(pair.Key, pair.Value.Value);
- return newdict;
- }
-
- public struct ValueStruct
- {
- public dynamic Value;
- public ValueTypes Type;
- public bool IsList;
- public ValueStruct(ValueTypes type, dynamic value, bool isList)
- {
- Value = value;
- Type = type;
- IsList = isList;
- }
- }
-
- public enum ValueTypes
- {
- List,
- Complex,
- String,
- Short,
- Int,
- Long,
- UShort,
- UInt,
- ULong,
- Double,
- Null,
- Bool,
- Unknown
- }
-
- public DtsodV22() { }
-
- public DtsodV22(string text)
- {
- foreach (KeyValuePair pair in Parse(text))
- Add(pair.Key, pair.Value);
- }
-
- public DtsodV22(Dictionary dict)
- {
- foreach (KeyValuePair pair in dict)
- Add(pair.Key, pair.Value);
- }
-
- // выдаёт Exception
- public new dynamic this[string key]
- {
- get => TryGetValue(key, out dynamic value) ? value : throw new Exception($"Dtsod[{key}] key not found");
- set
- {
- if (!TrySetValue(key, value)) throw new Exception($"Dtsod[{key}] key not found");
- }
- }
-
- // не выдаёт KeyNotFoundException
- public bool TryGetValue(string key, out dynamic value)
- {
- try
- {
- value = base[key].Value;
- return true;
- }
- catch (KeyNotFoundException)
- {
- value = null;
- return false;
- }
- }
- public bool TrySetValue(string key, dynamic value)
- {
- try
- {
- bool isList = value is IList;
- base[key] = new(base[key].Type, value, isList);
- return true;
- }
- catch (KeyNotFoundException)
- { return false; }
- }
-
- DtsodV22 Parse(string text)
- {
- Dictionary parsed = new();
- int i = 0;
- for (; i < text.Length; i++)
- ReadName();
- return new DtsodV22(parsed);
-
- // СЛОМАНО
- /*void ReadCommentLine()
- {
- for (; i < text.Length && text[i] != '\n'; i++) Debug("h", text[i].ToString());
- }*/
-
- void ReadName()
- {
-
- bool isListElem = false;
- dynamic value;
- StringBuilder defaultNameBuilder = new();
-
- for (; i < text.Length; i++)
- {
- switch (text[i])
- {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- break;
- case ':':
- i++;
- string name = defaultNameBuilder.ToString();
- value = ReadValue(out ValueTypes type, out bool isList);
- if (isListElem)
- {
- if (!parsed.ContainsKey(name))
- parsed.Add(name, new(type, new List(), isList));
- parsed[name].Value.Add(value);
- }
- else parsed.Add(name, new(type, value, isList));
- return;
- // строка, начинающаяся с # будет считаться комментом
- case '#':
- //ReadCommentLine();
- break;
- case '}':
- throw new Exception("Parse.ReadName() error: unexpected '}' at " + i + " char");
- // если $ перед названием параметра поставить, значение value добавится в лист с названием name
- case '$':
- if (defaultNameBuilder.ToString().Length != 0)
- throw new Exception("Parse.ReadName() error: unexpected '$' at " + i + " char");
- isListElem = true;
- break;
- case ';':
- throw new Exception("Parse.ReadName() error: unexpected ';' at " + i + " char");
- default:
- defaultNameBuilder.Append(text[i]);
- break;
- }
- }
- }
-
- dynamic ReadValue(out ValueTypes outType, out bool isList)
- {
- ValueTypes type = ValueTypes.Unknown;
- isList = false;
- dynamic value = null;
-
- string ReadString()
- {
- i++;
- StringBuilder valueBuilder = new();
- valueBuilder.Append('"');
- for (; text[i] != '"' || text[i - 1] == '\\'; i++)
- {
- valueBuilder.Append(text[i]);
- }
- valueBuilder.Append('"');
- type = ValueTypes.String;
- return valueBuilder.ToString();
- }
-
- List ReadList()
- {
- i++;
- List output = new();
- StringBuilder valueBuilder = new();
- for (; text[i] != ']'; i++)
- {
- switch (text[i])
- {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- break;
- case ',':
- ParseValueToRightType(valueBuilder.ToString());
- output.Add(value);
- valueBuilder.Clear();
- break;
- default:
- valueBuilder.Append(text[i]);
- break;
- }
- }
- if (valueBuilder.Length > 0)
- {
- ParseValueToRightType(valueBuilder.ToString());
- output.Add(value);
- }
- type = ValueTypes.List;
- return output;
- }
-
- Dictionary ReadComplex()
- {
- StringBuilder valueBuilder = new();
- int balance = 1;
- i++;
- for (; balance != 0; i++)
- {
- switch (text[i])
- {
- case '"':
- valueBuilder.Append(ReadString());
- break;
- case '}':
- balance--;
- if (balance != 0)
- valueBuilder.Append(text[i]);
- break;
- case '{':
- balance++;
- valueBuilder.Append(text[i]);
- break;
- default:
- valueBuilder.Append(text[i]);
- break;
- }
- }
- i--; // i++ в for выполняется даже когда balance == 0, то есть text[i] получается == ;, что ломает всё
- type = ValueTypes.Complex;
- return Parse(valueBuilder.ToString());
- }
-
- void ParseValueToRightType(string stringValue)
- {
- switch (stringValue)
- {
-
- // bool
- case "true":
- case "false":
- type = ValueTypes.Bool;
- value = stringValue.ToBool();
- break;
- // null
- case "null":
- type = ValueTypes.Null;
- value = null;
- break;
- default:
- if (stringValue.Contains('"'))
- {
- type = ValueTypes.String;
- value = stringValue.Remove(stringValue.Length - 1).Remove(0, 1);
- }
- // double
- else if (stringValue.Contains('.'))
- {
- type = ValueTypes.Double;
- value = stringValue.ToDouble();
- }
- // ushort; ulong; uint
- else if (stringValue.Length > 2 && stringValue[stringValue.Length - 2] == 'u')
- {
- switch (stringValue[stringValue.Length - 1])
- {
- case 's':
- type = ValueTypes.UShort;
- value = stringValue.Remove(stringValue.Length - 2).ToUShort();
- break;
- case 'i':
- type = ValueTypes.UInt;
- value = stringValue.Remove(stringValue.Length - 2).ToUInt();
- break;
- case 'l':
- type = ValueTypes.ULong;
- value = stringValue.Remove(stringValue.Length - 2).ToULong();
- break;
- default:
- throw new Exception($"Dtsod.Parse.ReadValue() error: value <{stringValue}> has wrong type");
- };
- }
- // short; long; int
- else
- switch (stringValue[stringValue.Length - 1])
- {
- case 's':
- type = ValueTypes.Short;
- value = stringValue.Remove(stringValue.Length - 1).ToShort();
- break;
- case 'l':
- type = ValueTypes.Long;
- value = stringValue.Remove(stringValue.Length - 1).ToLong();
- break;
- default:
- type = ValueTypes.Int;
- value = stringValue.ToInt();
- break;
- }
- break;
- };
- }
-
- StringBuilder defaultValueBuilder = new();
- for (; i < text.Length; i++)
- {
- switch (text[i])
- {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- break;
- case '"':
- value = ReadString();
- break;
- case '[':
- value = ReadList();
- break;
- case '{':
- value = ReadComplex();
- break;
- case ';':
- switch (type)
- {
- case ValueTypes.String:
- ParseValueToRightType(value);
- break;
- case ValueTypes.Unknown:
- ParseValueToRightType(defaultValueBuilder.ToString());
- break;
- case ValueTypes.List:
- isList = true;
- break;
- };
- outType = type;
- return value;
- // строка, начинающаяся с # будет считаться комментом
- case '#':
- //ReadCommentLine();
- break;
- default:
- defaultValueBuilder.Append(text[i]);
- break;
- }
- }
- throw new Exception("Dtsod.Parse.ReadValue error: wtf it's the end of function");
- }
- }
-
- public override string ToString() => Deconstruct(this);
-
- ushort tabCount = 0;
- string Deconstruct(DtsodV22 dtsod)
- {
- StringBuilder outBuilder = new();
- foreach (string key in dtsod.Keys)
- {
- outBuilder.Append('\t', tabCount);
- outBuilder.Append(key);
- outBuilder.Append(": ");
- dtsod.TryGetValue(key, out ValueStruct value);
- switch (value.Type)
- {
- case ValueTypes.List:
- outBuilder.Append('[').Append(StringConverter.MergeToString((IEnumerable