diff --git a/Aaru.Helpers/.editorconfig b/Aaru.Helpers/.editorconfig new file mode 100644 index 000000000..103a5d927 --- /dev/null +++ b/Aaru.Helpers/.editorconfig @@ -0,0 +1,1342 @@ +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = false +max_line_length = 120 +tab_width = 2 +trim_trailing_whitespace = false +ij_continuation_indent_size = 4 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = true +ij_smart_tabs = false +ij_visual_guides = +ij_wrap_on_typing = false + +# Microsoft .NET properties +csharp_preferred_modifier_order = public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion +csharp_space_after_keywords_in_control_flow_statements = false +csharp_style_namespace_declarations = file_scoped:warning +csharp_style_prefer_utf8_string_literals = true:warning +csharp_style_var_elsewhere = false:suggestion +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_using_directive_placement = outside_namespace:silent +dotnet_naming_rule.private_constants_rule.import_to_resharper = as_predefined +dotnet_naming_rule.private_constants_rule.severity = warning +dotnet_naming_rule.private_constants_rule.style = all_upper_style +dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols +dotnet_naming_rule.unity_serialized_field_rule.import_to_resharper = True +dotnet_naming_rule.unity_serialized_field_rule.resharper_description = Unity serialized field +dotnet_naming_rule.unity_serialized_field_rule.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef +dotnet_naming_rule.unity_serialized_field_rule.severity = warning +dotnet_naming_rule.unity_serialized_field_rule.style = lower_camel_case_style +dotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field_symbols +dotnet_naming_style.all_upper_style.capitalization = all_upper +dotnet_naming_style.all_upper_style.word_separator = _ +dotnet_naming_style.lower_camel_case_style.capitalization = camel_case +dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field +dotnet_naming_symbols.private_constants_symbols.required_modifiers = const +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = * +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds = +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:warning +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion +dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_require_accessibility_modifiers = never:suggestion + +# ReSharper properties +resharper_align_first_arg_by_paren = false +resharper_align_linq_query = true +resharper_align_multiline_argument = true +resharper_align_multiline_array_and_object_initializer = false +resharper_align_multiline_binary_expressions_chain = true +resharper_align_multiline_binary_patterns = true +resharper_align_multiline_calls_chain = true +resharper_align_multiline_expression = true +resharper_align_multiline_expression_braces = true +resharper_align_multiline_extends_list = true +resharper_align_multiline_for_stmt = true +resharper_align_multiline_list_pattern = true +resharper_align_multiline_parameter = true +resharper_align_multiline_property_pattern = true +resharper_align_multiline_switch_expression = true +resharper_align_multiple_declaration = true +resharper_align_multline_type_parameter_constrains = true +resharper_align_multline_type_parameter_list = true +resharper_align_ternary = align_all +resharper_align_tuple_components = true +resharper_autodetect_indent_settings = true +resharper_braces_for_for = required_for_multiline +resharper_braces_for_foreach = required_for_multiline +resharper_braces_for_ifelse = required_for_multiline +resharper_braces_for_while = required_for_multiline +resharper_builtin_type_apply_to_native_integer = false +resharper_constructor_or_destructor_body = expression_body +resharper_csharp_align_first_arg_by_paren = true +resharper_csharp_empty_block_style = together_same_line +resharper_csharp_place_comments_at_first_column = true +resharper_csharp_prefer_qualified_reference = false +resharper_default_value_when_type_not_evident = default_expression +resharper_enforce_line_ending_style = true +resharper_formatter_off_tag = @formatter:off +resharper_formatter_on_tag = @formatter:on +resharper_formatter_tags_enabled = true +resharper_for_built_in_types = use_var_when_evident +resharper_function_declaration_return_type_style = on_single_line +resharper_function_definition_return_type_style = on_single_line +resharper_html_pi_attribute_style = first_attribute_on_single_line +resharper_indent_anonymous_method_block = false +resharper_indent_preprocessor_if = outdent +resharper_indent_preprocessor_other = outdent +resharper_indent_preprocessor_region = outdent +resharper_int_align = true +resharper_int_align_bitfield_sizes = true +resharper_int_align_comments = true +resharper_int_align_declaration_names = true +resharper_int_align_enum_initializers = true +resharper_int_align_eq = true +resharper_keep_existing_embedded_arrangement = false +resharper_keep_existing_initializer_arrangement = false +resharper_keep_existing_linebreaks = false +resharper_keep_existing_list_patterns_arrangement = false +resharper_keep_existing_property_patterns_arrangement = false +resharper_keep_existing_switch_expression_arrangement = false +resharper_line_break_after_colon_in_member_initializer_lists = on_single_line +resharper_line_break_before_requires_clause = on_single_line +resharper_linkage_specification_indentation = all +resharper_local_function_body = expression_body +resharper_member_initializer_list_style = on_single_line +resharper_method_or_operator_body = expression_body +resharper_outdent_binary_ops = true +resharper_outdent_binary_pattern_ops = true +resharper_outdent_commas = true +resharper_outdent_dots = true +resharper_outdent_statement_labels = true +resharper_parentheses_redundancy_style = remove +resharper_place_attribute_on_same_line = false +resharper_place_simple_embedded_statement_on_same_line = false +resharper_place_simple_initializer_on_single_line = false +resharper_qualified_using_at_nested_scope = true +resharper_show_autodetect_configure_formatting_tip = false +resharper_simple_block_style = on_single_line +resharper_simple_case_statement_style = line_break +resharper_simple_embedded_statement_style = on_single_line +resharper_space_after_ptr_in_data_member = false +resharper_space_after_ptr_in_method = false +resharper_space_after_ref_in_data_member = false +resharper_space_after_ref_in_method = false +resharper_space_before_ptr_in_data_member = true +resharper_space_before_ptr_in_method = true +resharper_space_before_ref_in_data_member = true +resharper_space_before_ref_in_method = true +resharper_space_before_template_params = false +resharper_space_within_empty_braces = false +resharper_toplevel_function_declaration_return_type_style = on_single_line +resharper_toplevel_function_definition_return_type_style = on_single_line +resharper_use_indent_from_vs = false +resharper_wrap_after_dot_in_method_calls = true +resharper_wrap_base_clause_style = chop_if_long +resharper_wrap_braced_init_list_style = chop_if_long +resharper_wrap_chained_binary_expressions = chop_if_long +resharper_wrap_chained_method_calls = chop_if_long +resharper_wrap_ctor_initializer_style = chop_if_long +resharper_wrap_lines = true +resharper_xmldoc_attribute_indent = align_by_first_attribute +resharper_xmldoc_attribute_style = first_attribute_on_single_line +resharper_xmldoc_pi_attribute_style = first_attribute_on_single_line + +# ReSharper inspection severities +resharper_annotate_can_be_null_parameter_highlighting = warning +resharper_annotate_can_be_null_type_member_highlighting = warning +resharper_annotate_not_null_parameter_highlighting = warning +resharper_annotate_not_null_type_member_highlighting = warning +resharper_arguments_style_anonymous_function_highlighting = warning +resharper_arguments_style_literal_highlighting = warning +resharper_arguments_style_named_expression_highlighting = warning +resharper_arguments_style_other_highlighting = warning +resharper_arguments_style_string_literal_highlighting = warning +resharper_arrange_accessor_owner_body_highlighting = warning +resharper_arrange_constructor_or_destructor_body_highlighting = warning +resharper_arrange_local_function_body_highlighting = warning +resharper_arrange_method_or_operator_body_highlighting = warning +resharper_arrange_redundant_parentheses_highlighting = hint +resharper_arrange_static_member_qualifier_highlighting = warning +resharper_arrange_this_qualifier_highlighting = hint +resharper_arrange_trailing_comma_in_multiline_lists_highlighting = warning +resharper_arrange_trailing_comma_in_singleline_lists_highlighting = warning +resharper_arrange_type_member_modifiers_highlighting = hint +resharper_arrange_type_modifiers_highlighting = hint +resharper_arrange_var_keywords_in_deconstructing_declaration_highlighting = warning +resharper_async_void_method_highlighting = warning +resharper_auto_property_can_be_made_get_only_global_highlighting = warning +resharper_auto_property_can_be_made_get_only_local_highlighting = warning +resharper_bad_attribute_brackets_spaces_highlighting = warning +resharper_bad_braces_spaces_highlighting = warning +resharper_bad_colon_spaces_highlighting = warning +resharper_bad_comma_spaces_highlighting = warning +resharper_bad_control_braces_indent_highlighting = warning +resharper_bad_control_braces_line_breaks_highlighting = warning +resharper_bad_declaration_braces_indent_highlighting = warning +resharper_bad_declaration_braces_line_breaks_highlighting = warning +resharper_bad_empty_braces_line_breaks_highlighting = warning +resharper_bad_expression_braces_indent_highlighting = warning +resharper_bad_expression_braces_line_breaks_highlighting = warning +resharper_bad_generic_brackets_spaces_highlighting = warning +resharper_bad_indent_highlighting = warning +resharper_bad_linq_line_breaks_highlighting = warning +resharper_bad_member_access_spaces_highlighting = warning +resharper_bad_namespace_braces_indent_highlighting = warning +resharper_bad_parens_line_breaks_highlighting = warning +resharper_bad_parens_spaces_highlighting = warning +resharper_bad_preprocessor_indent_highlighting = warning +resharper_bad_semicolon_spaces_highlighting = warning +resharper_bad_spaces_after_keyword_highlighting = warning +resharper_bad_square_brackets_spaces_highlighting = warning +resharper_bad_switch_braces_indent_highlighting = warning +resharper_bad_symbol_spaces_highlighting = warning +resharper_built_in_type_reference_style_for_member_access_highlighting = hint +resharper_built_in_type_reference_style_highlighting = hint +resharper_check_for_reference_equality_instead_1_highlighting = warning +resharper_check_for_reference_equality_instead_2_highlighting = warning +resharper_check_for_reference_equality_instead_3_highlighting = warning +resharper_check_for_reference_equality_instead_4_highlighting = warning +resharper_class_can_be_sealed_global_highlighting = warning +resharper_class_can_be_sealed_local_highlighting = warning +resharper_class_never_instantiated_global_highlighting = warning +resharper_class_never_instantiated_local_highlighting = warning +resharper_class_with_virtual_members_never_inherited_global_highlighting = warning +resharper_class_with_virtual_members_never_inherited_local_highlighting = warning +resharper_comment_typo_highlighting = none +resharper_compare_non_constrained_generic_with_null_highlighting = warning +resharper_convert_closure_to_method_group_highlighting = warning +resharper_convert_conditional_ternary_expression_to_switch_expression_highlighting = warning +resharper_convert_if_do_to_while_highlighting = warning +resharper_convert_if_statement_to_conditional_ternary_expression_highlighting = warning +resharper_convert_if_statement_to_null_coalescing_assignment_highlighting = warning +resharper_convert_if_statement_to_null_coalescing_expression_highlighting = warning +resharper_convert_if_statement_to_return_statement_highlighting = warning +resharper_convert_if_statement_to_switch_statement_highlighting = warning +resharper_convert_if_to_or_expression_highlighting = warning +resharper_convert_nullable_to_short_form_highlighting = warning +resharper_convert_switch_statement_to_switch_expression_highlighting = warning +resharper_convert_to_auto_property_highlighting = warning +resharper_convert_to_auto_property_when_possible_highlighting = warning +resharper_convert_to_auto_property_with_private_setter_highlighting = warning +resharper_convert_to_compound_assignment_highlighting = warning +resharper_convert_to_constant_global_highlighting = warning +resharper_convert_to_constant_local_highlighting = warning +resharper_convert_to_lambda_expression_highlighting = warning +resharper_convert_to_local_function_highlighting = warning +resharper_convert_to_null_coalescing_compound_assignment_highlighting = warning +resharper_convert_to_primary_constructor_highlighting = warning +resharper_convert_to_static_class_highlighting = warning +resharper_convert_to_using_declaration_highlighting = warning +resharper_cpp_enforce_cv_qualifiers_order_highlighting = hint +resharper_cpp_enforce_cv_qualifiers_placement_highlighting = hint +resharper_cpp_enforce_do_statement_braces_highlighting = hint +resharper_cpp_enforce_for_statement_braces_highlighting = hint +resharper_cpp_enforce_function_declaration_style_highlighting = hint +resharper_cpp_enforce_if_statement_braces_highlighting = hint +resharper_cpp_enforce_type_alias_code_style_highlighting = hint +resharper_cpp_enforce_while_statement_braces_highlighting = hint +resharper_cpp_remove_redundant_braces_highlighting = hint +resharper_double_negation_in_pattern_highlighting = warning +resharper_double_negation_operator_highlighting = warning +resharper_event_never_invoked_global_highlighting = warning +resharper_event_never_subscribed_to_global_highlighting = warning +resharper_event_never_subscribed_to_local_highlighting = warning +resharper_field_can_be_made_read_only_global_highlighting = warning +resharper_field_can_be_made_read_only_local_highlighting = warning +resharper_foreach_can_be_converted_to_query_using_another_get_enumerator_highlighting = warning +resharper_foreach_can_be_partly_converted_to_query_using_another_get_enumerator_highlighting = none +resharper_for_can_be_converted_to_foreach_highlighting = warning +resharper_heap_view_boxing_allocation_highlighting = none +resharper_heap_view_closure_allocation_highlighting = none +resharper_heap_view_delegate_allocation_highlighting = none +resharper_heap_view_object_allocation_evident_highlighting = none +resharper_heap_view_object_allocation_highlighting = none +resharper_identifier_typo_highlighting = none +resharper_incorrect_blank_lines_near_braces_highlighting = warning +resharper_inheritdoc_consider_usage_highlighting = warning +resharper_inline_out_variable_declaration_highlighting = warning +resharper_inline_temporary_variable_highlighting = warning +resharper_introduce_optional_parameters_global_highlighting = warning +resharper_introduce_optional_parameters_local_highlighting = warning +resharper_invert_condition_1_highlighting = warning +resharper_invert_if_highlighting = warning +resharper_invocation_is_skipped_highlighting = warning +resharper_invoke_as_extension_method_highlighting = warning +resharper_join_declaration_and_initializer_highlighting = warning +resharper_join_null_check_with_usage_highlighting = warning +resharper_lambda_expression_must_be_static_highlighting = warning +resharper_local_function_can_be_made_static_highlighting = warning +resharper_loop_can_be_converted_to_query_highlighting = warning +resharper_loop_can_be_partly_converted_to_query_highlighting = warning +resharper_member_can_be_file_local_highlighting = warning +resharper_member_can_be_internal_highlighting = warning +resharper_member_can_be_made_static_global_highlighting = warning +resharper_member_can_be_made_static_local_highlighting = warning +resharper_member_can_be_private_global_highlighting = warning +resharper_member_can_be_private_local_highlighting = warning +resharper_member_can_be_protected_global_highlighting = warning +resharper_member_can_be_protected_local_highlighting = warning +resharper_merge_and_pattern_highlighting = warning +resharper_merge_cast_with_type_check_highlighting = warning +resharper_merge_conditional_expression_highlighting = warning +resharper_merge_into_logical_pattern_highlighting = warning +resharper_merge_into_negated_pattern_highlighting = warning +resharper_merge_into_pattern_highlighting = warning +resharper_merge_nested_property_patterns_highlighting = warning +resharper_merge_sequential_checks_highlighting = warning +resharper_method_has_async_overload_highlighting = warning +resharper_method_has_async_overload_with_cancellation_highlighting = warning +resharper_method_supports_cancellation_highlighting = warning +resharper_missing_blank_lines_highlighting = warning +resharper_missing_linebreak_highlighting = warning +resharper_missing_space_highlighting = warning +resharper_more_specific_foreach_variable_type_available_highlighting = warning +resharper_move_to_existing_positional_deconstruction_pattern_highlighting = warning +resharper_move_variable_declaration_inside_loop_condition_highlighting = warning +resharper_multiple_spaces_highlighting = warning +resharper_multiple_statements_on_one_line_highlighting = warning +resharper_multiple_type_members_on_one_line_highlighting = warning +resharper_negation_of_relational_pattern_highlighting = warning +resharper_negative_equality_expression_highlighting = warning +resharper_nested_string_interpolation_highlighting = warning +resharper_not_accessed_field_global_highlighting = warning +resharper_nullable_warning_suppression_is_used_highlighting = warning +resharper_outdent_is_off_prev_level_highlighting = warning +resharper_out_parameter_value_is_always_discarded_global_highlighting = warning +resharper_parameter_only_used_for_precondition_check_global_highlighting = warning +resharper_parameter_type_can_be_enumerable_global_highlighting = warning +resharper_parameter_type_can_be_enumerable_local_highlighting = warning +resharper_pass_string_interpolation_highlighting = warning +resharper_possible_unintended_queryable_as_enumerable_highlighting = warning +resharper_property_can_be_made_init_only_global_highlighting = warning +resharper_property_can_be_made_init_only_local_highlighting = warning +resharper_public_constructor_in_abstract_class_highlighting = warning +resharper_raw_string_can_be_simplified_highlighting = warning +resharper_redundant_accessor_body_highlighting = warning +resharper_redundant_always_match_subpattern_highlighting = warning +resharper_redundant_array_creation_expression_highlighting = warning +resharper_redundant_attribute_parentheses_highlighting = warning +resharper_redundant_attribute_usage_property_highlighting = warning +resharper_redundant_base_qualifier_highlighting = warning +resharper_redundant_blank_lines_highlighting = warning +resharper_redundant_collection_initializer_element_braces_highlighting = warning +resharper_redundant_configure_await_highlighting = warning +resharper_redundant_declaration_semicolon_highlighting = warning +resharper_redundant_discard_designation_highlighting = warning +resharper_redundant_empty_object_creation_argument_list_highlighting = warning +resharper_redundant_enum_case_label_for_default_section_highlighting = warning +resharper_redundant_explicit_params_array_creation_highlighting = warning +resharper_redundant_fixed_pointer_declaration_highlighting = warning +resharper_redundant_if_else_block_highlighting = warning +resharper_redundant_immediate_delegate_invocation_highlighting = warning +resharper_redundant_is_before_relational_pattern_highlighting = warning +resharper_redundant_lambda_signature_parentheses_highlighting = warning +resharper_redundant_overload_global_highlighting = warning +resharper_redundant_overload_local_highlighting = warning +resharper_redundant_pattern_parentheses_highlighting = warning +resharper_redundant_property_pattern_clause_highlighting = warning +resharper_redundant_query_order_by_ascending_keyword_highlighting = warning +resharper_redundant_range_bound_highlighting = warning +resharper_redundant_readonly_modifier_highlighting = warning +resharper_redundant_space_highlighting = warning +resharper_redundant_string_interpolation_highlighting = warning +resharper_redundant_to_string_call_for_value_type_highlighting = warning +resharper_redundant_verbatim_prefix_highlighting = warning +resharper_redundant_verbatim_string_prefix_highlighting = warning +resharper_redundant_with_expression_highlighting = warning +resharper_remove_constructor_invocation_highlighting = warning +resharper_remove_redundant_braces_highlighting = warning +resharper_remove_redundant_or_statement_false_highlighting = warning +resharper_remove_redundant_or_statement_true_highlighting = warning +resharper_remove_to_list_1_highlighting = warning +resharper_remove_to_list_2_highlighting = warning +resharper_replace_auto_property_with_computed_property_highlighting = warning +resharper_replace_conditional_expression_with_null_coalescing_highlighting = warning +resharper_replace_object_pattern_with_var_pattern_highlighting = warning +resharper_replace_slice_with_range_indexer_highlighting = warning +resharper_replace_substring_with_range_indexer_highlighting = warning +resharper_replace_with_field_keyword_highlighting = warning +resharper_replace_with_first_or_default_1_highlighting = warning +resharper_replace_with_first_or_default_2_highlighting = warning +resharper_replace_with_first_or_default_3_highlighting = warning +resharper_replace_with_first_or_default_4_highlighting = warning +resharper_replace_with_last_or_default_1_highlighting = warning +resharper_replace_with_last_or_default_2_highlighting = warning +resharper_replace_with_last_or_default_3_highlighting = warning +resharper_replace_with_last_or_default_4_highlighting = warning +resharper_replace_with_of_type_1_highlighting = warning +resharper_replace_with_of_type_2_highlighting = warning +resharper_replace_with_of_type_3_highlighting = warning +resharper_replace_with_of_type_any_1_highlighting = warning +resharper_replace_with_of_type_any_2_highlighting = warning +resharper_replace_with_of_type_count_1_highlighting = warning +resharper_replace_with_of_type_count_2_highlighting = warning +resharper_replace_with_of_type_first_1_highlighting = warning +resharper_replace_with_of_type_first_2_highlighting = warning +resharper_replace_with_of_type_first_or_default_1_highlighting = warning +resharper_replace_with_of_type_first_or_default_2_highlighting = warning +resharper_replace_with_of_type_last_1_highlighting = warning +resharper_replace_with_of_type_last_2_highlighting = warning +resharper_replace_with_of_type_last_or_default_1_highlighting = warning +resharper_replace_with_of_type_last_or_default_2_highlighting = warning +resharper_replace_with_of_type_long_count_highlighting = warning +resharper_replace_with_of_type_single_1_highlighting = warning +resharper_replace_with_of_type_single_2_highlighting = warning +resharper_replace_with_of_type_single_or_default_1_highlighting = warning +resharper_replace_with_of_type_single_or_default_2_highlighting = warning +resharper_replace_with_of_type_where_highlighting = warning +resharper_replace_with_simple_assignment_false_highlighting = warning +resharper_replace_with_simple_assignment_true_highlighting = warning +resharper_replace_with_single_assignment_false_highlighting = warning +resharper_replace_with_single_assignment_true_highlighting = warning +resharper_replace_with_single_call_to_any_highlighting = warning +resharper_replace_with_single_call_to_count_highlighting = warning +resharper_replace_with_single_call_to_first_highlighting = warning +resharper_replace_with_single_call_to_first_or_default_highlighting = warning +resharper_replace_with_single_call_to_last_highlighting = warning +resharper_replace_with_single_call_to_last_or_default_highlighting = warning +resharper_replace_with_single_call_to_single_highlighting = warning +resharper_replace_with_single_call_to_single_or_default_highlighting = warning +resharper_replace_with_single_or_default_1_highlighting = warning +resharper_replace_with_single_or_default_2_highlighting = warning +resharper_replace_with_single_or_default_3_highlighting = warning +resharper_replace_with_single_or_default_4_highlighting = warning +resharper_replace_with_string_is_null_or_empty_highlighting = warning +resharper_return_type_can_be_enumerable_global_highlighting = warning +resharper_return_type_can_be_enumerable_local_highlighting = warning +resharper_safe_cast_is_used_as_type_check_highlighting = warning +resharper_separate_control_transfer_statement_highlighting = warning +resharper_similar_anonymous_type_nearby_highlighting = warning +resharper_simplify_conditional_ternary_expression_highlighting = warning +resharper_simplify_linq_expression_use_all_highlighting = warning +resharper_simplify_linq_expression_use_any_highlighting = warning +resharper_simplify_linq_expression_use_min_by_and_max_by_highlighting = warning +resharper_simplify_string_interpolation_highlighting = warning +resharper_specify_string_comparison_highlighting = warning +resharper_string_ends_with_is_culture_specific_highlighting = warning +resharper_string_literal_as_interpolation_argument_highlighting = warning +resharper_string_literal_typo_highlighting = warning +resharper_string_starts_with_is_culture_specific_highlighting = warning +resharper_struct_can_be_made_read_only_highlighting = warning +resharper_struct_member_can_be_made_read_only_highlighting = warning +resharper_suggest_base_type_for_parameter_highlighting = none +resharper_suggest_base_type_for_parameter_in_constructor_highlighting = warning +resharper_suggest_var_or_type_built_in_types_highlighting = hint +resharper_suggest_var_or_type_deconstruction_declarations_highlighting = warning +resharper_suggest_var_or_type_elsewhere_highlighting = hint +resharper_suggest_var_or_type_simple_types_highlighting = hint +resharper_swap_via_deconstruction_highlighting = warning +resharper_switch_expression_handles_some_known_enum_values_with_exception_in_default_highlighting = warning +resharper_switch_statement_handles_some_known_enum_values_with_default_highlighting = none +resharper_switch_statement_missing_some_enum_cases_no_default_highlighting = none +resharper_tabs_and_spaces_mismatch_highlighting = warning +resharper_tabs_are_disallowed_highlighting = warning +resharper_tabs_outside_indent_highlighting = warning +resharper_tail_recursive_call_highlighting = warning +resharper_too_wide_local_variable_scope_highlighting = warning +resharper_try_cast_always_succeeds_highlighting = warning +resharper_try_statements_can_be_merged_highlighting = warning +resharper_type_parameter_can_be_variant_highlighting = warning +resharper_unnecessary_whitespace_highlighting = warning +resharper_unused_member_global_highlighting = warning +resharper_unused_member_hierarchy_global_highlighting = warning +resharper_unused_member_in_super_global_highlighting = warning +resharper_unused_method_return_value_global_highlighting = warning +resharper_unused_parameter_global_highlighting = warning +resharper_unused_type_global_highlighting = warning +resharper_use_array_creation_expression_1_highlighting = warning +resharper_use_array_creation_expression_2_highlighting = warning +resharper_use_array_empty_method_highlighting = warning +resharper_use_await_using_highlighting = warning +resharper_use_cancellation_token_for_i_async_enumerable_highlighting = warning +resharper_use_collection_count_property_highlighting = warning +resharper_use_configure_await_false_highlighting = warning +resharper_use_deconstruction_highlighting = warning +resharper_use_empty_types_field_highlighting = warning +resharper_use_event_args_empty_field_highlighting = warning +resharper_use_format_specifier_in_format_string_highlighting = warning +resharper_use_indexed_property_highlighting = warning +resharper_use_index_from_end_expression_highlighting = warning +resharper_use_is_operator_1_highlighting = warning +resharper_use_is_operator_2_highlighting = warning +resharper_use_method_any_0_highlighting = warning +resharper_use_method_any_1_highlighting = warning +resharper_use_method_any_2_highlighting = warning +resharper_use_method_any_3_highlighting = warning +resharper_use_method_any_4_highlighting = warning +resharper_use_method_is_instance_of_type_highlighting = warning +resharper_use_nameof_expression_for_part_of_the_string_highlighting = warning +resharper_use_nameof_expression_highlighting = warning +resharper_use_nameof_for_dependency_property_highlighting = warning +resharper_use_name_of_instead_of_type_of_highlighting = warning +resharper_use_negated_pattern_in_is_expression_highlighting = warning +resharper_use_negated_pattern_matching_highlighting = warning +resharper_use_nullable_annotation_instead_of_attribute_highlighting = warning +resharper_use_nullable_attributes_supported_by_compiler_highlighting = warning +resharper_use_null_propagation_highlighting = warning +resharper_use_object_or_collection_initializer_highlighting = warning +resharper_use_pattern_matching_highlighting = warning +resharper_use_positional_deconstruction_pattern_highlighting = warning +resharper_use_raw_string_highlighting = warning +resharper_use_string_interpolation_highlighting = warning +resharper_use_switch_case_pattern_variable_highlighting = warning +resharper_use_throw_if_null_method_highlighting = warning +resharper_use_unsigned_right_shift_operator_highlighting = warning +resharper_use_verbatim_string_highlighting = warning +resharper_use_with_expression_to_copy_anonymous_object_highlighting = warning +resharper_use_with_expression_to_copy_record_highlighting = warning +resharper_use_with_expression_to_copy_struct_highlighting = warning +resharper_use_with_expression_to_copy_tuple_highlighting = warning +resharper_virtual_member_never_overridden_global_highlighting = warning +resharper_virtual_member_never_overridden_local_highlighting = warning +resharper_web_config_module_not_resolved_highlighting = warning +resharper_web_config_type_not_resolved_highlighting = warning +resharper_web_config_wrong_module_highlighting = warning +resharper_with_expression_instead_of_initializer_highlighting = warning +resharper_wrong_indent_size_highlighting = warning + +[*.css] +ij_css_align_closing_brace_with_properties = false +ij_css_blank_lines_around_nested_selector = 1 +ij_css_blank_lines_between_blocks = 1 +ij_css_block_comment_add_space = false +ij_css_brace_placement = end_of_line +ij_css_enforce_quotes_on_format = false +ij_css_hex_color_long_format = false +ij_css_hex_color_lower_case = false +ij_css_hex_color_short_format = false +ij_css_hex_color_upper_case = false +ij_css_keep_blank_lines_in_code = 2 +ij_css_keep_indents_on_empty_lines = false +ij_css_keep_single_line_blocks = false +ij_css_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_css_space_after_colon = true +ij_css_space_before_opening_brace = true +ij_css_use_double_quotes = true +ij_css_value_alignment = do_not_align + +[*.csv] +max_line_length = 2147483647 +ij_csv_wrap_long_lines = false +indent_style = tab +tab_width = 1 + +[*.dart] +max_line_length = 80 + +[*.less] +indent_size = 2 +ij_less_align_closing_brace_with_properties = false +ij_less_blank_lines_around_nested_selector = 1 +ij_less_blank_lines_between_blocks = 1 +ij_less_block_comment_add_space = false +ij_less_brace_placement = 0 +ij_less_enforce_quotes_on_format = false +ij_less_hex_color_long_format = false +ij_less_hex_color_lower_case = false +ij_less_hex_color_short_format = false +ij_less_hex_color_upper_case = false +ij_less_keep_blank_lines_in_code = 2 +ij_less_keep_indents_on_empty_lines = false +ij_less_keep_single_line_blocks = false +ij_less_line_comment_add_space = false +ij_less_line_comment_at_first_column = false +ij_less_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_less_space_after_colon = true +ij_less_space_before_opening_brace = true +ij_less_use_double_quotes = true +ij_less_value_alignment = 0 + +[*.pp] +indent_size = 2 +tab_width = 2 +ij_continuation_indent_size = 2 +ij_puppet_keep_indents_on_empty_lines = false + +[*.properties] +ij_properties_align_group_field_declarations = true +ij_properties_keep_blank_lines = false +ij_properties_key_value_delimiter = equals +ij_properties_spaces_around_key_value_delimiter = true + +[*.sass] +indent_size = 2 +ij_sass_align_closing_brace_with_properties = false +ij_sass_blank_lines_around_nested_selector = 1 +ij_sass_blank_lines_between_blocks = 1 +ij_sass_brace_placement = 0 +ij_sass_enforce_quotes_on_format = false +ij_sass_hex_color_long_format = false +ij_sass_hex_color_lower_case = false +ij_sass_hex_color_short_format = false +ij_sass_hex_color_upper_case = false +ij_sass_keep_blank_lines_in_code = 2 +ij_sass_keep_indents_on_empty_lines = false +ij_sass_keep_single_line_blocks = false +ij_sass_line_comment_add_space = false +ij_sass_line_comment_at_first_column = false +ij_sass_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_sass_space_after_colon = true +ij_sass_space_before_opening_brace = true +ij_sass_use_double_quotes = true +ij_sass_value_alignment = 0 + +[*.scss] +indent_size = 2 +ij_scss_align_closing_brace_with_properties = false +ij_scss_blank_lines_around_nested_selector = 1 +ij_scss_blank_lines_between_blocks = 1 +ij_scss_block_comment_add_space = false +ij_scss_brace_placement = 0 +ij_scss_enforce_quotes_on_format = false +ij_scss_hex_color_long_format = false +ij_scss_hex_color_lower_case = false +ij_scss_hex_color_short_format = false +ij_scss_hex_color_upper_case = false +ij_scss_keep_blank_lines_in_code = 2 +ij_scss_keep_indents_on_empty_lines = false +ij_scss_keep_single_line_blocks = false +ij_scss_line_comment_add_space = false +ij_scss_line_comment_at_first_column = false +ij_scss_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_scss_space_after_colon = true +ij_scss_space_before_opening_brace = true +ij_scss_use_double_quotes = true +ij_scss_value_alignment = 0 + +[*.slim] +indent_size = 2 +ij_slim_keep_indents_on_empty_lines = false + +[*.twig] +ij_twig_keep_indents_on_empty_lines = false +ij_twig_spaces_inside_comments_delimiters = true +ij_twig_spaces_inside_delimiters = true +ij_twig_spaces_inside_variable_delimiters = true + +[*.vue] +indent_size = 2 +tab_width = 2 +ij_continuation_indent_size = 4 +ij_vue_indent_children_of_top_level = template +ij_vue_interpolation_new_line_after_start_delimiter = true +ij_vue_interpolation_new_line_before_end_delimiter = true +ij_vue_interpolation_wrap = off +ij_vue_keep_indents_on_empty_lines = false +ij_vue_spaces_within_interpolation_expressions = true + +[.editorconfig] +ij_editorconfig_align_group_field_declarations = true +ij_editorconfig_space_after_colon = false +ij_editorconfig_space_after_comma = true +ij_editorconfig_space_before_colon = false +ij_editorconfig_space_before_comma = false +ij_editorconfig_spaces_around_assignment_operators = true + +[{*.ad,*.adoc,*.asciidoc,.asciidoctorconfig}] +ij_asciidoc_blank_lines_after_header = 1 +ij_asciidoc_blank_lines_keep_after_header = 1 +ij_asciidoc_formatting_enabled = true +ij_asciidoc_one_sentence_per_line = true + +[{*.ant,*.appxmanifest,*.axml,*.cscfg,*.csdef,*.disco,*.dotsettings,*.filelayout,*.fxml,*.jhm,*.jnlp,*.jrxml,*.manifest,*.myapp,*.nuspec,*.rng,*.sdef,*.stylecop,*.svcmap,*.tld,*.wadcfgx,*.webref,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,StyleCop.Cache}] +ij_xml_align_attributes = true +ij_xml_align_text = false +ij_xml_attribute_wrap = on_every_item +ij_xml_block_comment_add_space = false +ij_xml_block_comment_at_first_column = true +ij_xml_keep_blank_lines = 2 +ij_xml_keep_indents_on_empty_lines = false +ij_xml_keep_line_breaks = true +ij_xml_keep_line_breaks_in_text = true +ij_xml_keep_whitespaces = false +ij_xml_keep_whitespaces_around_cdata = preserve +ij_xml_keep_whitespaces_inside_cdata = false +ij_xml_line_comment_at_first_column = true +ij_xml_space_after_tag_name = false +ij_xml_space_around_equals_in_attribute = false +ij_xml_space_inside_empty_tag = false +ij_xml_text_wrap = normal +ij_xml_use_custom_settings = false +indent_size = 2 +tab_width = 2 +ij_continuation_indent_size = 4 + +[{*.applescript,*.scpt}] +indent_size = 2 +tab_width = 2 +ij_continuation_indent_size = 4 +ij_applescript_align_multiline_binary_operation = true +ij_applescript_align_multiline_parameters = true +ij_applescript_align_multiline_parameters_in_calls = true +ij_applescript_binary_operation_sign_on_next_line = false +ij_applescript_binary_operation_wrap = off +ij_applescript_block_brace_style = next_line +ij_applescript_call_parameters_new_line_after_left_paren = false +ij_applescript_call_parameters_right_paren_on_new_line = false +ij_applescript_call_parameters_wrap = off +ij_applescript_else_on_new_line = true +ij_applescript_keep_blank_lines_in_code = 2 +ij_applescript_keep_first_column_comment = true +ij_applescript_keep_indents_on_empty_lines = false +ij_applescript_keep_line_breaks = true +ij_applescript_method_brace_style = next_line +ij_applescript_method_parameters_new_line_after_left_paren = false +ij_applescript_method_parameters_right_paren_on_new_line = false +ij_applescript_method_parameters_wrap = off +ij_applescript_parentheses_expression_new_line_after_left_paren = false +ij_applescript_parentheses_expression_right_paren_on_new_line = false +ij_applescript_space_after_colon = true +ij_applescript_space_after_comma = true +ij_applescript_space_after_comma_in_type_arguments = true +ij_applescript_space_before_colon = true +ij_applescript_space_before_comma = false +ij_applescript_space_before_else_keyword = true +ij_applescript_space_before_else_left_brace = true +ij_applescript_space_before_if_parentheses = false +ij_applescript_space_before_method_call_parentheses = false +ij_applescript_space_before_method_left_brace = true +ij_applescript_space_before_method_parentheses = false +ij_applescript_space_before_while_keyword = true +ij_applescript_spaces_around_additive_operators = true +ij_applescript_spaces_around_assignment_operators = true +ij_applescript_spaces_around_equality_operators = true +ij_applescript_spaces_around_logical_operators = true +ij_applescript_spaces_around_multiplicative_operators = true +ij_applescript_spaces_around_relational_operators = true +ij_applescript_spaces_around_shift_operators = true +ij_applescript_spaces_around_unary_operator = false +ij_applescript_spaces_within_if_parentheses = false +ij_applescript_spaces_within_method_call_parentheses = false +ij_applescript_spaces_within_method_parentheses = false +ij_applescript_special_else_if_treatment = true + +[{*.ats,*.cts,*.mts,*.ts}] +ij_continuation_indent_size = 4 +ij_typescript_align_imports = true +ij_typescript_align_multiline_array_initializer_expression = true +ij_typescript_align_multiline_binary_operation = true +ij_typescript_align_multiline_chained_methods = true +ij_typescript_align_multiline_extends_list = false +ij_typescript_align_multiline_for = true +ij_typescript_align_multiline_parameters = true +ij_typescript_align_multiline_parameters_in_calls = true +ij_typescript_align_multiline_ternary_operation = true +ij_typescript_align_object_properties = 1 +ij_typescript_align_union_types = true +ij_typescript_align_var_statements = 2 +ij_typescript_array_initializer_new_line_after_left_brace = false +ij_typescript_array_initializer_right_brace_on_new_line = false +ij_typescript_array_initializer_wrap = on_every_item +ij_typescript_assignment_wrap = on_every_item +ij_typescript_binary_operation_sign_on_next_line = false +ij_typescript_binary_operation_wrap = on_every_item +ij_typescript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/** +ij_typescript_blank_lines_after_imports = 1 +ij_typescript_blank_lines_around_class = 1 +ij_typescript_blank_lines_around_field = 0 +ij_typescript_blank_lines_around_field_in_interface = 0 +ij_typescript_blank_lines_around_function = 1 +ij_typescript_blank_lines_around_method = 1 +ij_typescript_blank_lines_around_method_in_interface = 1 +ij_typescript_block_brace_style = next_line +ij_typescript_block_comment_add_space = false +ij_typescript_block_comment_at_first_column = true +ij_typescript_call_parameters_new_line_after_left_paren = false +ij_typescript_call_parameters_right_paren_on_new_line = false +ij_typescript_call_parameters_wrap = on_every_item +ij_typescript_catch_on_new_line = true +ij_typescript_chained_call_dot_on_new_line = true +ij_typescript_class_brace_style = next_line +ij_typescript_comma_on_new_line = false +ij_typescript_do_while_brace_force = always +ij_typescript_else_on_new_line = false +ij_typescript_enforce_trailing_comma = keep +ij_typescript_enum_constants_wrap = on_every_item +ij_typescript_extends_keyword_wrap = normal +ij_typescript_extends_list_wrap = on_every_item +ij_typescript_field_prefix = _ +ij_typescript_file_name_style = relaxed +ij_typescript_finally_on_new_line = true +ij_typescript_for_brace_force = if_multiline +ij_typescript_for_statement_new_line_after_left_paren = false +ij_typescript_for_statement_right_paren_on_new_line = false +ij_typescript_for_statement_wrap = on_every_item +ij_typescript_force_quote_style = true +ij_typescript_force_semicolon_style = true +ij_typescript_function_expression_brace_style = next_line +ij_typescript_if_brace_force = never +ij_typescript_import_merge_members = global +ij_typescript_import_prefer_absolute_path = true +ij_typescript_import_sort_members = true +ij_typescript_import_sort_module_name = true +ij_typescript_import_use_node_resolution = true +ij_typescript_imports_wrap = on_every_item +ij_typescript_indent_case_from_switch = true +ij_typescript_indent_chained_calls = true +ij_typescript_indent_package_children = 0 +ij_typescript_jsdoc_include_types = false +ij_typescript_jsx_attribute_value = braces +ij_typescript_keep_blank_lines_in_code = 2 +ij_typescript_keep_first_column_comment = true +ij_typescript_keep_indents_on_empty_lines = false +ij_typescript_keep_line_breaks = true +ij_typescript_keep_simple_blocks_in_one_line = false +ij_typescript_keep_simple_methods_in_one_line = false +ij_typescript_line_comment_add_space = true +ij_typescript_line_comment_at_first_column = false +ij_typescript_method_brace_style = next_line +ij_typescript_method_call_chain_wrap = on_every_item +ij_typescript_method_parameters_new_line_after_left_paren = false +ij_typescript_method_parameters_right_paren_on_new_line = false +ij_typescript_method_parameters_wrap = on_every_item +ij_typescript_object_literal_wrap = on_every_item +ij_typescript_object_types_wrap = on_every_item +ij_typescript_parentheses_expression_new_line_after_left_paren = false +ij_typescript_parentheses_expression_right_paren_on_new_line = false +ij_typescript_place_assignment_sign_on_next_line = false +ij_typescript_prefer_as_type_cast = false +ij_typescript_prefer_explicit_types_function_expression_returns = false +ij_typescript_prefer_explicit_types_function_returns = false +ij_typescript_prefer_explicit_types_vars_fields = false +ij_typescript_prefer_parameters_wrap = false +ij_typescript_property_prefix = +ij_typescript_reformat_c_style_comments = false +ij_typescript_space_after_colon = true +ij_typescript_space_after_comma = true +ij_typescript_space_after_dots_in_rest_parameter = false +ij_typescript_space_after_generator_mult = true +ij_typescript_space_after_property_colon = true +ij_typescript_space_after_quest = true +ij_typescript_space_after_type_colon = true +ij_typescript_space_after_unary_not = false +ij_typescript_space_before_async_arrow_lparen = false +ij_typescript_space_before_catch_keyword = true +ij_typescript_space_before_catch_left_brace = false +ij_typescript_space_before_catch_parentheses = false +ij_typescript_space_before_class_lbrace = false +ij_typescript_space_before_class_left_brace = true +ij_typescript_space_before_colon = true +ij_typescript_space_before_comma = false +ij_typescript_space_before_do_left_brace = false +ij_typescript_space_before_else_keyword = true +ij_typescript_space_before_else_left_brace = false +ij_typescript_space_before_finally_keyword = true +ij_typescript_space_before_finally_left_brace = false +ij_typescript_space_before_for_left_brace = false +ij_typescript_space_before_for_parentheses = false +ij_typescript_space_before_for_semicolon = false +ij_typescript_space_before_function_left_parenth = false +ij_typescript_space_before_generator_mult = false +ij_typescript_space_before_if_left_brace = false +ij_typescript_space_before_if_parentheses = false +ij_typescript_space_before_method_call_parentheses = false +ij_typescript_space_before_method_left_brace = false +ij_typescript_space_before_method_parentheses = false +ij_typescript_space_before_property_colon = false +ij_typescript_space_before_quest = true +ij_typescript_space_before_switch_left_brace = false +ij_typescript_space_before_switch_parentheses = false +ij_typescript_space_before_try_left_brace = false +ij_typescript_space_before_type_colon = false +ij_typescript_space_before_unary_not = false +ij_typescript_space_before_while_keyword = true +ij_typescript_space_before_while_left_brace = false +ij_typescript_space_before_while_parentheses = false +ij_typescript_spaces_around_additive_operators = true +ij_typescript_spaces_around_arrow_function_operator = true +ij_typescript_spaces_around_assignment_operators = true +ij_typescript_spaces_around_bitwise_operators = true +ij_typescript_spaces_around_equality_operators = true +ij_typescript_spaces_around_logical_operators = true +ij_typescript_spaces_around_multiplicative_operators = true +ij_typescript_spaces_around_relational_operators = true +ij_typescript_spaces_around_shift_operators = true +ij_typescript_spaces_around_unary_operator = false +ij_typescript_spaces_within_array_initializer_brackets = false +ij_typescript_spaces_within_brackets = false +ij_typescript_spaces_within_catch_parentheses = false +ij_typescript_spaces_within_for_parentheses = false +ij_typescript_spaces_within_if_parentheses = false +ij_typescript_spaces_within_imports = false +ij_typescript_spaces_within_interpolation_expressions = false +ij_typescript_spaces_within_method_call_parentheses = false +ij_typescript_spaces_within_method_parentheses = false +ij_typescript_spaces_within_object_literal_braces = false +ij_typescript_spaces_within_object_type_braces = true +ij_typescript_spaces_within_parentheses = false +ij_typescript_spaces_within_switch_parentheses = false +ij_typescript_spaces_within_type_assertion = false +ij_typescript_spaces_within_union_types = true +ij_typescript_spaces_within_while_parentheses = false +ij_typescript_special_else_if_treatment = true +ij_typescript_ternary_operation_signs_on_next_line = false +ij_typescript_ternary_operation_wrap = on_every_item +ij_typescript_union_types_wrap = on_every_item +ij_typescript_use_chained_calls_group_indents = false +ij_typescript_use_double_quotes = true +ij_typescript_use_explicit_js_extension = auto +ij_typescript_use_path_mapping = always +ij_typescript_use_public_modifier = false +ij_typescript_use_semicolon_after_statement = true +ij_typescript_var_declaration_wrap = normal +ij_typescript_while_brace_force = always +ij_typescript_while_on_new_line = false +ij_typescript_wrap_comments = false + +[{*.bash,*.sh,*.zsh}] +indent_size = 2 +tab_width = 2 +ij_shell_binary_ops_start_line = false +ij_shell_keep_column_alignment_padding = false +ij_shell_minify_program = false +ij_shell_redirect_followed_by_space = false +ij_shell_switch_cases_indented = true +ij_shell_use_unix_line_separator = true +indent_style = space + +[{*.cjs,*.js}] +ij_continuation_indent_size = 4 +ij_javascript_align_imports = true +ij_javascript_align_multiline_array_initializer_expression = true +ij_javascript_align_multiline_binary_operation = true +ij_javascript_align_multiline_chained_methods = false +ij_javascript_align_multiline_extends_list = true +ij_javascript_align_multiline_for = true +ij_javascript_align_multiline_parameters = true +ij_javascript_align_multiline_parameters_in_calls = true +ij_javascript_align_multiline_ternary_operation = true +ij_javascript_align_object_properties = 1 +ij_javascript_align_union_types = false +ij_javascript_align_var_statements = 2 +ij_javascript_array_initializer_new_line_after_left_brace = false +ij_javascript_array_initializer_right_brace_on_new_line = false +ij_javascript_array_initializer_wrap = on_every_item +ij_javascript_assignment_wrap = on_every_item +ij_javascript_binary_operation_sign_on_next_line = false +ij_javascript_binary_operation_wrap = on_every_item +ij_javascript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/** +ij_javascript_blank_lines_after_imports = 1 +ij_javascript_blank_lines_around_class = 1 +ij_javascript_blank_lines_around_field = 0 +ij_javascript_blank_lines_around_function = 1 +ij_javascript_blank_lines_around_method = 1 +ij_javascript_block_brace_style = next_line +ij_javascript_block_comment_add_space = false +ij_javascript_block_comment_at_first_column = true +ij_javascript_call_parameters_new_line_after_left_paren = false +ij_javascript_call_parameters_right_paren_on_new_line = false +ij_javascript_call_parameters_wrap = on_every_item +ij_javascript_catch_on_new_line = true +ij_javascript_chained_call_dot_on_new_line = true +ij_javascript_class_brace_style = next_line +ij_javascript_comma_on_new_line = false +ij_javascript_do_while_brace_force = always +ij_javascript_else_on_new_line = true +ij_javascript_enforce_trailing_comma = remove +ij_javascript_extends_keyword_wrap = normal +ij_javascript_extends_list_wrap = on_every_item +ij_javascript_field_prefix = _ +ij_javascript_file_name_style = relaxed +ij_javascript_finally_on_new_line = true +ij_javascript_for_brace_force = if_multiline +ij_javascript_for_statement_new_line_after_left_paren = false +ij_javascript_for_statement_right_paren_on_new_line = false +ij_javascript_for_statement_wrap = on_every_item +ij_javascript_force_quote_style = true +ij_javascript_force_semicolon_style = true +ij_javascript_function_expression_brace_style = next_line +ij_javascript_if_brace_force = if_multiline +ij_javascript_import_merge_members = global +ij_javascript_import_prefer_absolute_path = true +ij_javascript_import_sort_members = true +ij_javascript_import_sort_module_name = true +ij_javascript_import_use_node_resolution = true +ij_javascript_imports_wrap = on_every_item +ij_javascript_indent_case_from_switch = true +ij_javascript_indent_chained_calls = true +ij_javascript_indent_package_children = 0 +ij_javascript_jsx_attribute_value = braces +ij_javascript_keep_blank_lines_in_code = 2 +ij_javascript_keep_first_column_comment = true +ij_javascript_keep_indents_on_empty_lines = false +ij_javascript_keep_line_breaks = true +ij_javascript_keep_simple_blocks_in_one_line = false +ij_javascript_keep_simple_methods_in_one_line = false +ij_javascript_line_comment_add_space = true +ij_javascript_line_comment_at_first_column = false +ij_javascript_method_brace_style = next_line +ij_javascript_method_call_chain_wrap = on_every_item +ij_javascript_method_parameters_new_line_after_left_paren = false +ij_javascript_method_parameters_right_paren_on_new_line = false +ij_javascript_method_parameters_wrap = on_every_item +ij_javascript_object_literal_wrap = on_every_item +ij_javascript_object_types_wrap = on_every_item +ij_javascript_parentheses_expression_new_line_after_left_paren = false +ij_javascript_parentheses_expression_right_paren_on_new_line = false +ij_javascript_place_assignment_sign_on_next_line = true +ij_javascript_prefer_as_type_cast = false +ij_javascript_prefer_explicit_types_function_expression_returns = false +ij_javascript_prefer_explicit_types_function_returns = false +ij_javascript_prefer_explicit_types_vars_fields = false +ij_javascript_prefer_parameters_wrap = false +ij_javascript_property_prefix = +ij_javascript_reformat_c_style_comments = true +ij_javascript_space_after_colon = true +ij_javascript_space_after_comma = true +ij_javascript_space_after_dots_in_rest_parameter = false +ij_javascript_space_after_generator_mult = true +ij_javascript_space_after_property_colon = true +ij_javascript_space_after_quest = true +ij_javascript_space_after_type_colon = true +ij_javascript_space_after_unary_not = false +ij_javascript_space_before_async_arrow_lparen = false +ij_javascript_space_before_catch_keyword = true +ij_javascript_space_before_catch_left_brace = false +ij_javascript_space_before_catch_parentheses = false +ij_javascript_space_before_class_lbrace = false +ij_javascript_space_before_class_left_brace = true +ij_javascript_space_before_colon = true +ij_javascript_space_before_comma = false +ij_javascript_space_before_do_left_brace = false +ij_javascript_space_before_else_keyword = true +ij_javascript_space_before_else_left_brace = false +ij_javascript_space_before_finally_keyword = true +ij_javascript_space_before_finally_left_brace = false +ij_javascript_space_before_for_left_brace = false +ij_javascript_space_before_for_parentheses = false +ij_javascript_space_before_for_semicolon = false +ij_javascript_space_before_function_left_parenth = false +ij_javascript_space_before_generator_mult = false +ij_javascript_space_before_if_left_brace = false +ij_javascript_space_before_if_parentheses = false +ij_javascript_space_before_method_call_parentheses = false +ij_javascript_space_before_method_left_brace = false +ij_javascript_space_before_method_parentheses = false +ij_javascript_space_before_property_colon = false +ij_javascript_space_before_quest = true +ij_javascript_space_before_switch_left_brace = false +ij_javascript_space_before_switch_parentheses = false +ij_javascript_space_before_try_left_brace = false +ij_javascript_space_before_type_colon = false +ij_javascript_space_before_unary_not = false +ij_javascript_space_before_while_keyword = true +ij_javascript_space_before_while_left_brace = false +ij_javascript_space_before_while_parentheses = false +ij_javascript_spaces_around_additive_operators = true +ij_javascript_spaces_around_arrow_function_operator = true +ij_javascript_spaces_around_assignment_operators = true +ij_javascript_spaces_around_bitwise_operators = true +ij_javascript_spaces_around_equality_operators = true +ij_javascript_spaces_around_logical_operators = true +ij_javascript_spaces_around_multiplicative_operators = true +ij_javascript_spaces_around_relational_operators = true +ij_javascript_spaces_around_shift_operators = true +ij_javascript_spaces_around_unary_operator = false +ij_javascript_spaces_within_array_initializer_brackets = false +ij_javascript_spaces_within_brackets = false +ij_javascript_spaces_within_catch_parentheses = false +ij_javascript_spaces_within_for_parentheses = false +ij_javascript_spaces_within_if_parentheses = false +ij_javascript_spaces_within_imports = false +ij_javascript_spaces_within_interpolation_expressions = false +ij_javascript_spaces_within_method_call_parentheses = false +ij_javascript_spaces_within_method_parentheses = false +ij_javascript_spaces_within_object_literal_braces = false +ij_javascript_spaces_within_object_type_braces = true +ij_javascript_spaces_within_parentheses = false +ij_javascript_spaces_within_switch_parentheses = false +ij_javascript_spaces_within_type_assertion = false +ij_javascript_spaces_within_union_types = true +ij_javascript_spaces_within_while_parentheses = false +ij_javascript_special_else_if_treatment = true +ij_javascript_ternary_operation_signs_on_next_line = false +ij_javascript_ternary_operation_wrap = on_every_item +ij_javascript_union_types_wrap = on_every_item +ij_javascript_use_chained_calls_group_indents = true +ij_javascript_use_double_quotes = true +ij_javascript_use_explicit_js_extension = auto +ij_javascript_use_path_mapping = always +ij_javascript_use_public_modifier = false +ij_javascript_use_semicolon_after_statement = true +ij_javascript_var_declaration_wrap = normal +ij_javascript_while_brace_force = always +ij_javascript_while_on_new_line = false +ij_javascript_wrap_comments = false + +[{*.comp,*.frag,*.fsh,*.geom,*.glsl,*.tesc,*.tese,*.vert,*.vsh}] +ij_glsl_keep_indents_on_empty_lines = false + +[{*.har,*.jsb2,*.jsb3,*.json,*.jsonc,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}] +indent_size = 2 +ij_json_array_wrapping = normal +ij_json_keep_blank_lines_in_code = 0 +ij_json_keep_indents_on_empty_lines = false +ij_json_keep_line_breaks = true +ij_json_keep_trailing_comma = false +ij_json_object_wrapping = normal +ij_json_property_alignment = align_on_value +ij_json_space_after_colon = true +ij_json_space_after_comma = true +ij_json_space_before_colon = false +ij_json_space_before_comma = false +ij_json_spaces_within_braces = false +ij_json_spaces_within_brackets = false +ij_json_wrap_long_lines = false +indent_style = space + +[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}] +ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3 +ij_html_align_attributes = true +ij_html_align_text = false +ij_html_attribute_wrap = normal +ij_html_block_comment_add_space = false +ij_html_block_comment_at_first_column = true +ij_html_do_not_align_children_of_min_lines = 0 +ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p +ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot +ij_html_enforce_quotes = false +ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var +ij_html_keep_blank_lines = 2 +ij_html_keep_indents_on_empty_lines = false +ij_html_keep_line_breaks = true +ij_html_keep_line_breaks_in_text = true +ij_html_keep_whitespaces = false +ij_html_keep_whitespaces_inside = span, pre, textarea +ij_html_line_comment_at_first_column = true +ij_html_new_line_after_last_attribute = never +ij_html_new_line_before_first_attribute = never +ij_html_quote_style = double +ij_html_remove_new_line_before_tags = br +ij_html_space_after_tag_name = false +ij_html_space_around_equality_in_attribute = false +ij_html_space_inside_empty_tag = false +ij_html_text_wrap = normal + +[{*.http,*.rest}] +indent_size = 0 +ij_continuation_indent_size = 4 +ij_http-request_call_parameters_wrap = normal +ij_http-request_method_parameters_wrap = split_into_lines +ij_http-request_space_before_comma = true +ij_http-request_spaces_around_assignment_operators = true + +[{*.markdown,*.md}] +ij_markdown_force_one_space_after_blockquote_symbol = true +ij_markdown_force_one_space_after_header_symbol = true +ij_markdown_force_one_space_after_list_bullet = true +ij_markdown_force_one_space_between_words = true +ij_markdown_format_tables = true +ij_markdown_insert_quote_arrows_on_wrap = true +ij_markdown_keep_indents_on_empty_lines = false +ij_markdown_keep_line_breaks_inside_text_blocks = true +ij_markdown_max_lines_around_block_elements = 1 +ij_markdown_max_lines_around_header = 1 +ij_markdown_max_lines_between_paragraphs = 1 +ij_markdown_min_lines_around_block_elements = 1 +ij_markdown_min_lines_around_header = 1 +ij_markdown_min_lines_between_paragraphs = 1 +ij_markdown_wrap_text_if_long = true +ij_markdown_wrap_text_inside_blockquotes = true + +[{*.ps1,*.psd1,*.psm1}] +max_line_length = 115 +ij_powershell_align_multiline_binary_operation = true +ij_powershell_align_multiline_chained_methods = false +ij_powershell_align_multiline_for = true +ij_powershell_align_multiline_parameters = true +ij_powershell_align_multiline_parameters_in_calls = false +ij_powershell_binary_operation_wrap = on_every_item +ij_powershell_block_brace_style = next_line +ij_powershell_call_parameters_new_line_after_left_paren = false +ij_powershell_call_parameters_right_paren_on_new_line = false +ij_powershell_call_parameters_wrap = on_every_item +ij_powershell_catch_on_new_line = true +ij_powershell_class_annotation_wrap = split_into_lines +ij_powershell_class_brace_style = next_line +ij_powershell_else_on_new_line = true +ij_powershell_field_annotation_wrap = off +ij_powershell_finally_on_new_line = true +ij_powershell_for_statement_new_line_after_left_paren = false +ij_powershell_for_statement_right_paren_on_new_line = false +ij_powershell_for_statement_wrap = on_every_item +ij_powershell_keep_blank_lines_in_code = 2 +ij_powershell_keep_first_column_comment = true +ij_powershell_keep_line_breaks = true +ij_powershell_keep_simple_blocks_in_one_line = true +ij_powershell_keep_simple_classes_in_one_line = false +ij_powershell_keep_simple_lambdas_in_one_line = true +ij_powershell_keep_simple_methods_in_one_line = true +ij_powershell_method_annotation_wrap = split_into_lines +ij_powershell_method_brace_style = next_line +ij_powershell_method_call_chain_wrap = on_every_item +ij_powershell_method_parameters_new_line_after_left_paren = false +ij_powershell_method_parameters_right_paren_on_new_line = false +ij_powershell_method_parameters_wrap = on_every_item +ij_powershell_parameter_annotation_wrap = off +ij_powershell_parentheses_expression_new_line_after_left_paren = false +ij_powershell_parentheses_expression_right_paren_on_new_line = false +ij_powershell_space_after_colon = true +ij_powershell_space_after_comma = true +ij_powershell_space_after_for_semicolon = true +ij_powershell_space_after_type_cast = false +ij_powershell_space_before_annotation_parameter_list = false +ij_powershell_space_before_array_initializer_left_brace = false +ij_powershell_space_before_catch_keyword = true +ij_powershell_space_before_catch_left_brace = false +ij_powershell_space_before_class_left_brace = false +ij_powershell_space_before_colon = true +ij_powershell_space_before_comma = false +ij_powershell_space_before_do_left_brace = false +ij_powershell_space_before_else_keyword = true +ij_powershell_space_before_else_left_brace = false +ij_powershell_space_before_finally_keyword = true +ij_powershell_space_before_finally_left_brace = false +ij_powershell_space_before_for_left_brace = false +ij_powershell_space_before_for_parentheses = false +ij_powershell_space_before_for_semicolon = false +ij_powershell_space_before_if_left_brace = false +ij_powershell_space_before_if_parentheses = false +ij_powershell_space_before_method_call_parentheses = false +ij_powershell_space_before_method_left_brace = false +ij_powershell_space_before_method_parentheses = false +ij_powershell_space_before_switch_left_brace = false +ij_powershell_space_before_switch_parentheses = false +ij_powershell_space_before_try_left_brace = false +ij_powershell_space_before_while_keyword = true +ij_powershell_space_before_while_left_brace = false +ij_powershell_space_before_while_parentheses = false +ij_powershell_space_within_empty_method_call_parentheses = false +ij_powershell_space_within_empty_method_parentheses = false +ij_powershell_spaces_around_additive_operators = true +ij_powershell_spaces_around_assignment_operators = true +ij_powershell_spaces_around_bitwise_operators = true +ij_powershell_spaces_around_logical_operators = true +ij_powershell_spaces_around_method_ref_dbl_colon = false +ij_powershell_spaces_around_multiplicative_operators = true +ij_powershell_spaces_around_relational_operators = true +ij_powershell_spaces_around_unary_operator = false +ij_powershell_spaces_within_annotation_parentheses = false +ij_powershell_spaces_within_braces = true +ij_powershell_spaces_within_brackets = false +ij_powershell_spaces_within_cast_parentheses = false +ij_powershell_spaces_within_for_parentheses = false +ij_powershell_spaces_within_if_parentheses = false +ij_powershell_spaces_within_method_call_parentheses = false +ij_powershell_spaces_within_method_parentheses = false +ij_powershell_spaces_within_parentheses = false +ij_powershell_spaces_within_switch_parentheses = false +ij_powershell_spaces_within_while_parentheses = false +ij_powershell_special_else_if_treatment = true +ij_powershell_while_on_new_line = false +ij_powershell_wrap_first_method_in_call_chain = false +ij_powershell_wrap_long_lines = false + +[{*.py,*.pyw}] +ij_python_align_collections_and_comprehensions = true +ij_python_align_multiline_imports = true +ij_python_align_multiline_parameters = true +ij_python_align_multiline_parameters_in_calls = true +ij_python_blank_line_at_file_end = false +ij_python_blank_lines_after_imports = 1 +ij_python_blank_lines_after_local_imports = 0 +ij_python_blank_lines_around_class = 1 +ij_python_blank_lines_around_method = 1 +ij_python_blank_lines_around_top_level_classes_functions = 2 +ij_python_blank_lines_before_first_method = 0 +ij_python_call_parameters_new_line_after_left_paren = false +ij_python_call_parameters_right_paren_on_new_line = false +ij_python_call_parameters_wrap = on_every_item +ij_python_dict_alignment = 0 +ij_python_dict_new_line_after_left_brace = false +ij_python_dict_new_line_before_right_brace = false +ij_python_dict_wrapping = 5 +ij_python_from_import_new_line_after_left_parenthesis = false +ij_python_from_import_new_line_before_right_parenthesis = false +ij_python_from_import_parentheses_force_if_multiline = false +ij_python_from_import_trailing_comma_if_multiline = false +ij_python_from_import_wrapping = 5 +ij_python_hang_closing_brackets = true +ij_python_keep_blank_lines_in_code = 1 +ij_python_keep_blank_lines_in_declarations = 1 +ij_python_keep_indents_on_empty_lines = false +ij_python_keep_line_breaks = true +ij_python_method_parameters_new_line_after_left_paren = false +ij_python_method_parameters_right_paren_on_new_line = false +ij_python_method_parameters_wrap = on_every_item +ij_python_new_line_after_colon = false +ij_python_new_line_after_colon_multi_clause = true +ij_python_optimize_imports_always_split_from_imports = false +ij_python_optimize_imports_case_insensitive_order = true +ij_python_optimize_imports_join_from_imports_with_same_source = false +ij_python_optimize_imports_sort_by_type_first = true +ij_python_optimize_imports_sort_imports = true +ij_python_optimize_imports_sort_names_in_from_imports = true +ij_python_space_after_comma = true +ij_python_space_after_number_sign = true +ij_python_space_after_py_colon = true +ij_python_space_before_backslash = true +ij_python_space_before_comma = false +ij_python_space_before_for_semicolon = false +ij_python_space_before_lbracket = false +ij_python_space_before_method_call_parentheses = false +ij_python_space_before_method_parentheses = false +ij_python_space_before_number_sign = true +ij_python_space_before_py_colon = false +ij_python_space_within_empty_method_call_parentheses = false +ij_python_space_within_empty_method_parentheses = false +ij_python_spaces_around_additive_operators = true +ij_python_spaces_around_assignment_operators = true +ij_python_spaces_around_bitwise_operators = true +ij_python_spaces_around_eq_in_keyword_argument = false +ij_python_spaces_around_eq_in_named_parameter = false +ij_python_spaces_around_equality_operators = true +ij_python_spaces_around_multiplicative_operators = true +ij_python_spaces_around_power_operator = true +ij_python_spaces_around_relational_operators = true +ij_python_spaces_around_shift_operators = true +ij_python_spaces_within_braces = false +ij_python_spaces_within_brackets = false +ij_python_spaces_within_method_call_parentheses = false +ij_python_spaces_within_method_parentheses = false +ij_python_use_continuation_indent_for_arguments = false +ij_python_use_continuation_indent_for_collection_and_comprehensions = false +ij_python_use_continuation_indent_for_parameters = true +ij_python_wrap_long_lines = false + +[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}] +ij_toml_keep_indents_on_empty_lines = false + +[{*.yaml,*.yml,pubspec.lock}] +indent_size = 2 +ij_yaml_align_values_properties = on_value +ij_yaml_autoinsert_sequence_marker = true +ij_yaml_block_mapping_on_new_line = false +ij_yaml_indent_sequence_value = true +ij_yaml_keep_indents_on_empty_lines = false +ij_yaml_keep_line_breaks = true +ij_yaml_sequence_on_new_line = false +ij_yaml_space_before_colon = false +ij_yaml_spaces_within_braces = true +ij_yaml_spaces_within_brackets = true +indent_style = space + +[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,cc,cginc,compute,cp,cpp,cppm,cs,cshtml,cu,cuh,cxx,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,uxml,vb,xaml,xamlx,xoml,xsd}] +indent_style = space +indent_size = 4 +tab_width = 4 diff --git a/Aaru.Helpers/.gitignore b/Aaru.Helpers/.gitignore new file mode 100644 index 000000000..05c540d38 --- /dev/null +++ b/Aaru.Helpers/.gitignore @@ -0,0 +1,595 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# 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 + +# 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/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.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 + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# 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 +# 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 + +# 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 + +# 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/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# 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/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube \ No newline at end of file diff --git a/Aaru.Helpers/Aaru.Helpers.csproj b/Aaru.Helpers/Aaru.Helpers.csproj new file mode 100644 index 000000000..02a2e0461 --- /dev/null +++ b/Aaru.Helpers/Aaru.Helpers.csproj @@ -0,0 +1,60 @@ + + + + 2.0 + {F8BDF57B-1571-4CD0-84B3-B422088D359A} + Library + Aaru.Helpers + Aaru.Helpers + $(Version) + true + 6.0.0-alpha9 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.Helpers + $(Version) + net8.0 + 12 + Contains helpers used by the Aaru Data Preservation Suite. + https://github.com/aaru-dps/ + LGPL-2.1-only + https://github.com/aaru-dps/Aaru.Helpers + true + en-US + true + true + snupkg + Natalia Portillo <claunia@claunia.com> + true + true + + + CS1591;CS1574 + + + + + + + $(Version)+{chash:8} + true + true + + + + + + + LICENSE.LGPL + + + ResXFileCodeGenerator + Localization.Designer.cs + + + + + + + \ No newline at end of file diff --git a/Aaru.Helpers/Aaru.Helpers.csproj.DotSettings b/Aaru.Helpers/Aaru.Helpers.csproj.DotSettings new file mode 100644 index 000000000..67ed7f8db --- /dev/null +++ b/Aaru.Helpers/Aaru.Helpers.csproj.DotSettings @@ -0,0 +1,5 @@ + + True \ No newline at end of file diff --git a/Aaru.Helpers/ArrayFill.cs b/Aaru.Helpers/ArrayFill.cs new file mode 100644 index 000000000..cbac721e8 --- /dev/null +++ b/Aaru.Helpers/ArrayFill.cs @@ -0,0 +1,79 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ArrayFill.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Fills an array with a specified value. +// +// --[ License ] -------------------------------------------------------------- +// +// No license specified by creator. +// +// Published on https://github.com/mykohsu/Extensions/blob/master/ArrayExtensions.cs +// +// Assuming open source. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// Copyright(C) 2014 mykohsu +// ****************************************************************************/ + +using System; +using System.Text; + +namespace Aaru.Helpers; + +public static partial class ArrayHelpers +{ + /// Fills an array with the specified value + /// Array + /// Value + /// Array type + public static void ArrayFill(T[] destinationArray, T value) => ArrayFill(destinationArray, new[] + { + value + }); + + /// Fills an array with the contents of the specified array + /// Array + /// Value + /// Array type + public static void ArrayFill(T[] destinationArray, T[] value) + { + ArgumentNullException.ThrowIfNull(destinationArray); + + if(value.Length > destinationArray.Length) + throw new ArgumentException(Localization.Length_of_value_array_must_not_be_more_than_length_of_destination); + + // set the initial array value + Array.Copy(value, destinationArray, value.Length); + + int arrayToFillHalfLength = destinationArray.Length / 2; + int copyLength; + + for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1) + Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength); + + Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength); + } + + /// Converts a byte array to its hexadecimal representation + /// Byte array + /// true to use uppercase + /// + public static string ByteArrayToHex(byte[] array, bool upper = false) + { + var sb = new StringBuilder(); + + for(long i = 0; i < array.LongLength; i++) + sb.Append($"{array[i]:x2}"); + + return upper ? sb.ToString().ToUpper() : sb.ToString(); + } +} \ No newline at end of file diff --git a/Aaru.Helpers/ArrayIsEmpty.cs b/Aaru.Helpers/ArrayIsEmpty.cs new file mode 100644 index 000000000..aa8302bfe --- /dev/null +++ b/Aaru.Helpers/ArrayIsEmpty.cs @@ -0,0 +1,49 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ArrayIsEmpty.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Methods for detecting an empty array. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Linq; + +namespace Aaru.Helpers; + +/// Helper operations to work with arrays +public static partial class ArrayHelpers +{ + /// Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20) + /// Array + /// True if null or whitespace + public static bool ArrayIsNullOrWhiteSpace(byte[] array) => array?.All(b => b is 0x00 or 0x20) != false; + + /// Checks if an array is null or filled with the NULL byte (0x00) + /// Array + /// True if null + public static bool ArrayIsNullOrEmpty(byte[] array) => array?.All(b => b == 0x00) != false; +} \ No newline at end of file diff --git a/Aaru.Helpers/BigEndianBitConverter.cs b/Aaru.Helpers/BigEndianBitConverter.cs new file mode 100644 index 000000000..cb1225bea --- /dev/null +++ b/Aaru.Helpers/BigEndianBitConverter.cs @@ -0,0 +1,323 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : BigEndianBitConverter.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Override of System.BitConverter that knows how to handle big-endian. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; + +namespace Aaru.Helpers; + +/// +/// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from +/// the meta data of System.BitConverter. This implementation allows for Endianness consideration. +/// +[SuppressMessage("ReSharper", "UnusedParameter.Global")] +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public static class BigEndianBitConverter +{ + /// Converts the specified double-precision floating point number to a 64-bit signed integer. + /// The number to convert. + /// A 64-bit signed integer whose value is equivalent to value. + /// It is not currently implemented + public static long DoubleToInt64Bits(double value) => throw new NotImplementedException(); + + /// Returns the specified Boolean value as an array of bytes. + /// A Boolean value. + /// An array of bytes with length 1. + public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified Unicode character value as an array of bytes. + /// A character to convert. + /// An array of bytes with length 2. + public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified double-precision floating point value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 8. + public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified single-precision floating point value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 4. + public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 32-bit signed integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 4. + public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 64-bit signed integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 8. + public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 16-bit signed integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 2. + public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 32-bit unsigned integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 4. + public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 64-bit unsigned integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 8. + public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 16-bit unsigned integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 2. + public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Converts the specified 64-bit signed integer to a double-precision floating point number. + /// The number to convert. + /// A double-precision floating point number whose value is equivalent to value. + public static double Int64BitsToDouble(long value) => throw new NotImplementedException(); + + /// Returns a Boolean value converted from one byte at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// true if the byte at in value is nonzero; otherwise, false. + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException(); + + /// Returns a Unicode character converted from two bytes at a specified position in a byte array. + /// An array. + /// The starting position within value. + /// A character formed by two bytes beginning at . + /// equals the length of value minus 1. + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException(); + + /// + /// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte + /// array. + /// + /// An array of bytes. + /// The starting position within value. + /// A double precision floating point number formed by eight bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 7, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException(); + + /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 16-bit signed integer formed by two bytes beginning at . + /// equals the length of value minus 1. + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static short ToInt16(byte[] value, int startIndex) => + BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex); + + /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 32-bit signed integer formed by four bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 3, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static int ToInt32(byte[] value, int startIndex) => + BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex); + + /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 64-bit signed integer formed by eight bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 7, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static long ToInt64(byte[] value, int startIndex) => + BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex); + + /// + /// Returns a single-precision floating point number converted from four bytes at a specified position in a byte + /// array. + /// + /// An array of bytes. + /// The starting position within value. + /// A single-precision floating point number formed by four bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 3, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static float ToSingle(byte[] value, int startIndex) => + BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex); + + /// + /// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string + /// representation. + /// + /// An array of bytes. + /// + /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding + /// element in value; for example, "7F-2C-4A". + /// + /// value is null. + public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray()); + + /// + /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal + /// string representation. + /// + /// An array of bytes. + /// The starting position within value. + /// + /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding + /// element in a subarray of value; for example, "7F-2C-4A". + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static string ToString(byte[] value, int startIndex) => + BitConverter.ToString(value.Reverse().ToArray(), startIndex); + + /// + /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal + /// string representation. + /// + /// An array of bytes. + /// The starting position within value. + /// The number of array elements in value to convert. + /// + /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding + /// element in a subarray of value; for example, "7F-2C-4A". + /// + /// value is null. + /// + /// startIndex or length is less than zero. -or- startIndex is greater + /// than zero and is greater than or equal to the length of value. + /// + /// + /// The combination of startIndex and length does not specify a position within + /// value; that is, the startIndex parameter is greater than the length of value minus the length parameter. + /// + public static string ToString(byte[] value, int startIndex, int length) => + BitConverter.ToString(value.Reverse().ToArray(), startIndex, length); + + /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array. + /// The array of bytes. + /// The starting position within value. + /// A 16-bit unsigned integer formed by two bytes beginning at startIndex. + /// startIndex equals the length of value minus 1. + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static ushort ToUInt16(byte[] value, int startIndex) => + BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex); + + /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 32-bit unsigned integer formed by four bytes beginning at startIndex. + /// + /// startIndex is greater than or equal to the length of value minus 3, and is + /// less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static uint ToUInt32(byte[] value, int startIndex) => + BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex); + + /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 64-bit unsigned integer formed by the eight bytes beginning at startIndex. + /// + /// startIndex is greater than or equal to the length of value minus 7, and is + /// less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static ulong ToUInt64(byte[] value, int startIndex) => + BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex); + + /// Converts a big endian byte array representation of a GUID into the .NET Guid structure + /// Byte array containing a GUID in big endian + /// Start of the byte array to process + /// Processed Guid + public static Guid ToGuid(byte[] value, int startIndex) => new(ToUInt32(value, 0 + startIndex), + ToUInt16(value, 4 + startIndex), + ToUInt16(value, 6 + startIndex), + value[8 + startIndex + 0], value[8 + startIndex + 1], + value[8 + startIndex + 2], value[8 + startIndex + 3], + value[8 + startIndex + 5], value[8 + startIndex + 5], + value[8 + startIndex + 6], + value[8 + startIndex + 7]); +} \ No newline at end of file diff --git a/Aaru.Helpers/BitEndian.cs b/Aaru.Helpers/BitEndian.cs new file mode 100644 index 000000000..72ae6fdf4 --- /dev/null +++ b/Aaru.Helpers/BitEndian.cs @@ -0,0 +1,50 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : BitEndian.cs +// Author(s) : Natalia Portillo +// +// Component : Common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines enumerations of bit endianness. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers; + +/// Describes the endianness of bits on a data structure +public enum BitEndian +{ + /// Little-endian, or least significant bit + Little, + /// Big-endian, or most significant bit + Big, + /// PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them + Pdp +} \ No newline at end of file diff --git a/Aaru.Helpers/CHS.cs b/Aaru.Helpers/CHS.cs new file mode 100644 index 000000000..d13c80b22 --- /dev/null +++ b/Aaru.Helpers/CHS.cs @@ -0,0 +1,49 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CHS.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Helpers for CHS<->LBA conversions +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers; + +/// Helper operations to work with CHS values +public static class CHS +{ + /// Converts a CHS position to a LBA one + /// Cylinder + /// Head + /// Sector + /// Number of heads + /// Number of sectors per track + /// + public static uint ToLBA(uint cyl, uint head, uint sector, uint maxHead, uint maxSector) => + maxHead == 0 || maxSector == 0 + ? (cyl * 16 + head) * 63 + sector - 1 + : (cyl * maxHead + head) * maxSector + sector - 1; +} \ No newline at end of file diff --git a/Aaru.Helpers/CompareBytes.cs b/Aaru.Helpers/CompareBytes.cs new file mode 100644 index 000000000..a06aaed9f --- /dev/null +++ b/Aaru.Helpers/CompareBytes.cs @@ -0,0 +1,72 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CompareBytes.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Compares two byte arrays. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers; + +public static partial class ArrayHelpers +{ + /// Compares two byte arrays + /// true if they are different in any way + /// true if they have the same size + /// Left array + /// Right array + public static void CompareBytes(out bool different, out bool sameSize, byte[] compareArray1, byte[] compareArray2) + { + different = false; + sameSize = true; + + long leastBytes; + + if(compareArray1.LongLength < compareArray2.LongLength) + { + sameSize = false; + leastBytes = compareArray1.LongLength; + } + else if(compareArray1.LongLength > compareArray2.LongLength) + { + sameSize = false; + leastBytes = compareArray2.LongLength; + } + else + leastBytes = compareArray1.LongLength; + + for(long i = 0; i < leastBytes; i++) + { + if(compareArray1[i] == compareArray2[i]) + continue; + + different = true; + + return; + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/CountBits.cs b/Aaru.Helpers/CountBits.cs new file mode 100644 index 000000000..44b81526c --- /dev/null +++ b/Aaru.Helpers/CountBits.cs @@ -0,0 +1,48 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CountBits.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Counts bits in a number. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers; + +/// Helper operations to count bits +public static class CountBits +{ + /// Counts the number of bits set to true in a number + /// Number + /// Bits set to true + public static int Count(uint number) + { + number -= number >> 1 & 0x55555555; + number = (number & 0x33333333) + (number >> 2 & 0x33333333); + + return (int)((number + (number >> 4) & 0x0F0F0F0F) * 0x01010101 >> 24); + } +} \ No newline at end of file diff --git a/Aaru.Helpers/DateHandlers.cs b/Aaru.Helpers/DateHandlers.cs new file mode 100644 index 000000000..ba80926df --- /dev/null +++ b/Aaru.Helpers/DateHandlers.cs @@ -0,0 +1,386 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DateHandlers.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Convert several timestamp formats to C# DateTime. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Text; +using Aaru.Console; + +namespace Aaru.Helpers; + +/// Helper operations for timestamp management (date and time) +public static class DateHandlers +{ + const string ISO9660_MODULE_NAME = "ISO9600ToDateTime handler"; + const string PASCAL_MODULE_NAME = "UCSDPascalToDateTime handler"; + const string DOS_MODULE_NAME = "DOSToDateTime handler"; + static readonly DateTime _lisaEpoch = new(1901, 1, 1, 0, 0, 0); + static readonly DateTime _macEpoch = new(1904, 1, 1, 0, 0, 0); + static readonly DateTime _unixEpoch = new(1970, 1, 1, 0, 0, 0); + /// Day 0 of Julian Date system + static readonly DateTime _julianEpoch = new(1858, 11, 17, 0, 0, 0); + static readonly DateTime _amigaEpoch = new(1978, 1, 1, 0, 0, 0); + + /// Converts a Macintosh timestamp to a .NET DateTime + /// Macintosh timestamp (seconds since 1st Jan. 1904) + /// .NET DateTime + public static DateTime MacToDateTime(ulong macTimeStamp) => _macEpoch.AddTicks((long)(macTimeStamp * 10000000)); + + /// Converts a Lisa timestamp to a .NET DateTime + /// Lisa timestamp (seconds since 1st Jan. 1901) + /// .NET DateTime + public static DateTime LisaToDateTime(uint lisaTimeStamp) => _lisaEpoch.AddSeconds(lisaTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixToDateTime(int unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixToDateTime(long unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// Seconds since 1st Jan. 1970) + /// Nanoseconds + /// .NET DateTime + public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) => + _unixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a High Sierra Format timestamp to a .NET DateTime + /// High Sierra Format timestamp + /// .NET DateTime + public static DateTime HighSierraToDateTime(byte[] vdDateTime) + { + var isoTime = new byte[17]; + Array.Copy(vdDateTime, 0, isoTime, 0, 16); + + return Iso9660ToDateTime(isoTime); + } + + // TODO: Timezone + /// Converts an ISO9660 timestamp to a .NET DateTime + /// ISO9660 timestamp + /// .NET DateTime + public static DateTime Iso9660ToDateTime(byte[] vdDateTime) + { + var twoCharValue = new byte[2]; + var fourCharValue = new byte[4]; + + fourCharValue[0] = vdDateTime[0]; + fourCharValue[1] = vdDateTime[1]; + fourCharValue[2] = vdDateTime[2]; + fourCharValue[3] = vdDateTime[3]; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, "year = \"{0}\"", + StringHandlers.CToString(fourCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(fourCharValue, Encoding.ASCII), out int year)) + year = 0; + + twoCharValue[0] = vdDateTime[4]; + twoCharValue[1] = vdDateTime[5]; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, "month = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int month)) + month = 0; + + twoCharValue[0] = vdDateTime[6]; + twoCharValue[1] = vdDateTime[7]; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, "day = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int day)) + day = 0; + + twoCharValue[0] = vdDateTime[8]; + twoCharValue[1] = vdDateTime[9]; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, "hour = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hour)) + hour = 0; + + twoCharValue[0] = vdDateTime[10]; + twoCharValue[1] = vdDateTime[11]; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, "minute = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int minute)) + minute = 0; + + twoCharValue[0] = vdDateTime[12]; + twoCharValue[1] = vdDateTime[13]; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, "second = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int second)) + second = 0; + + twoCharValue[0] = vdDateTime[14]; + twoCharValue[1] = vdDateTime[15]; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, "hundredths = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hundredths)) + hundredths = 0; + + AaruConsole.DebugWriteLine(ISO9660_MODULE_NAME, + "decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);", + year, month, day, hour, minute, second, hundredths * 10); + + var difference = (sbyte)vdDateTime[16]; + + var decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Utc); + + return decodedDt.AddMinutes(difference * -15); + } + + /// Converts a VMS timestamp to a .NET DateTime + /// VMS timestamp (tenths of microseconds since day 0 of the Julian Date) + /// .NET DateTime + /// C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC + public static DateTime VmsToDateTime(ulong vmsDate) + { + double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail + + return _julianEpoch.AddMilliseconds(delta); + } + + /// Converts an Amiga timestamp to a .NET DateTime + /// Days since the 1st Jan. 1978 + /// Minutes since o'clock + /// Ticks + /// .NET DateTime + public static DateTime AmigaToDateTime(uint days, uint minutes, uint ticks) + { + DateTime temp = _amigaEpoch.AddDays(days); + temp = temp.AddMinutes(minutes); + + return temp.AddMilliseconds(ticks * 20); + } + + /// Converts an UCSD Pascal timestamp to a .NET DateTime + /// UCSD Pascal timestamp + /// .NET DateTime + public static DateTime UcsdPascalToDateTime(short dateRecord) + { + int year = ((dateRecord & 0xFE00) >> 9) + 1900; + int day = (dateRecord & 0x01F0) >> 4; + int month = dateRecord & 0x000F; + + AaruConsole.DebugWriteLine(PASCAL_MODULE_NAME, "dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", + dateRecord, year, month, day); + + return new DateTime(year, month, day); + } + + /// Converts a DOS timestamp to a .NET DateTime + /// Date + /// Time + /// .NET DateTime + public static DateTime DosToDateTime(ushort date, ushort time) + { + int year = ((date & 0xFE00) >> 9) + 1980; + int month = (date & 0x1E0) >> 5; + int day = date & 0x1F; + int hour = (time & 0xF800) >> 11; + int minute = (time & 0x7E0) >> 5; + int second = (time & 0x1F) * 2; + + AaruConsole.DebugWriteLine(DOS_MODULE_NAME, "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}", date, year, + month, day); + + AaruConsole.DebugWriteLine(DOS_MODULE_NAME, "time = 0x{0:X4}, hour = {1}, minute = {2}, second = {3}", time, + hour, minute, second); + + DateTime dosDate; + + try + { + dosDate = new DateTime(year, month, day, hour, minute, second); + } + catch(ArgumentOutOfRangeException) + { + dosDate = new DateTime(1980, 1, 1, 0, 0, 0); + } + + return dosDate; + } + + /// Converts a CP/M timestamp to .NET DateTime + /// CP/M timestamp + /// .NET DateTime + public static DateTime CpmToDateTime(byte[] timestamp) + { + var days = BitConverter.ToUInt16(timestamp, 0); + int hours = timestamp[2]; + int minutes = timestamp[3]; + + DateTime temp = _amigaEpoch.AddDays(days); + temp = temp.AddHours(hours); + temp = temp.AddMinutes(minutes); + + return temp; + } + + /// Converts an ECMA timestamp to a .NET DateTime + /// Timezone + /// Year + /// Month + /// Day + /// Hour + /// Minute + /// Second + /// Centiseconds + /// Hundreds of microseconds + /// Microseconds + /// + public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day, byte hour, + byte minute, byte second, byte centiseconds, byte hundredsOfMicroseconds, + byte microseconds) + { + var specification = (byte)((typeAndTimeZone & 0xF000) >> 12); + + long ticks = (long)centiseconds * 100000 + (long)hundredsOfMicroseconds * 1000 + (long)microseconds * 10; + + if(specification == 0) + return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks); + + var preOffset = (ushort)(typeAndTimeZone & 0xFFF); + short offset; + + if((preOffset & 0x800) == 0x800) + offset = (short)(preOffset | 0xF000); + else + offset = (short)(preOffset & 0x7FF); + + switch(offset) + { + case -2047: + return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).AddTicks(ticks); + case < -1440 or > 1440: + offset = 0; + + break; + } + + return new DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)).AddTicks(ticks). + DateTime; + } + + /// Converts a Solaris high resolution timestamp to .NET DateTime + /// Solaris high resolution timestamp + /// .NET DateTime + public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) => _unixEpoch.AddTicks((long)(hrTimeStamp / 100)); + + /// Converts an OS-9 timestamp to .NET DateTime + /// OS-9 timestamp + /// .NET DateTime + public static DateTime Os9ToDateTime(byte[] date) + { + if(date == null || date.Length != 3 && date.Length != 5) + return DateTime.MinValue; + + DateTime os9Date; + + try + { + os9Date = date.Length == 5 + ? new DateTime(1900 + date[0], date[1], date[2], date[3], date[4], 0) + : new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0); + } + catch(ArgumentOutOfRangeException) + { + os9Date = new DateTime(1900, 0, 0, 0, 0, 0); + } + + return os9Date; + } + + /// Converts a LIF timestamp to .NET DateTime + /// LIF timestamp + /// .NET DateTime + public static DateTime LifToDateTime(byte[] date) => date is not { Length: 6 } + ? new DateTime(1970, 1, 1, 0, 0, 0) + : LifToDateTime(date[0], date[1], date[2], date[3], + date[4], date[5]); + + /// Converts a LIF timestamp to .NET DateTime + /// Yer + /// Month + /// Day + /// Hour + /// Minute + /// Second + /// .NET DateTime + public static DateTime LifToDateTime(byte year, byte month, byte day, byte hour, byte minute, byte second) + { + try + { + int iyear = (year >> 4) * 10 + (year & 0xF); + int imonth = (month >> 4) * 10 + (month & 0xF); + int iday = (day >> 4) * 10 + (day & 0xF); + int iminute = (minute >> 4) * 10 + (minute & 0xF); + int ihour = (hour >> 4) * 10 + (hour & 0xF); + int isecond = (second >> 4) * 10 + (second & 0xF); + + if(iyear >= 70) + iyear += 1900; + else + iyear += 2000; + + return new DateTime(iyear, imonth, iday, ihour, iminute, isecond); + } + catch(ArgumentOutOfRangeException) + { + return new DateTime(1970, 1, 1, 0, 0, 0); + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/Extensions.cs b/Aaru.Helpers/Extensions.cs new file mode 100644 index 000000000..c48b97066 --- /dev/null +++ b/Aaru.Helpers/Extensions.cs @@ -0,0 +1,72 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Extensions.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides class extensions. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.IO; + +namespace Aaru.Helpers; + +public static class Extensions +{ + /// + /// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the + /// position within the stream by the number of bytes read.
Guarantees the whole count of bytes is read or EOF is + /// found + ///
+ /// Stream to extend + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the + /// values between and ( + - 1) replaced by the bytes + /// read from the current source. + /// + /// + /// The zero-based byte offset in at which to begin storing the data read from + /// the current stream. + /// + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if the end + /// of the stream has been reached. + /// + public static int EnsureRead(this Stream s, byte[] buffer, int offset, int count) + { + var pos = 0; + int read; + + do + { + read = s.Read(buffer, pos + offset, count - pos); + pos += read; + } while(read > 0); + + return pos; + } +} \ No newline at end of file diff --git a/Aaru.Helpers/IO/ForcedSeekStream.cs b/Aaru.Helpers/IO/ForcedSeekStream.cs new file mode 100644 index 000000000..fd48c2f49 --- /dev/null +++ b/Aaru.Helpers/IO/ForcedSeekStream.cs @@ -0,0 +1,257 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ForcedSeekStream.cs +// Author(s) : Natalia Portillo +// +// Component : Filters. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides a seekable stream from a forward-readable stream. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; + +namespace Aaru.Helpers.IO; + +/// +/// ForcedSeekStream allows to seek a forward-readable stream (like System.IO.Compression streams) by doing the +/// slow and known trick of rewinding and forward reading until arriving the desired position. +/// +/// +public sealed class ForcedSeekStream : Stream where T : Stream +{ + const int BUFFER_LEN = 1048576; + readonly string _backFile; + readonly FileStream _backStream; + readonly T _baseStream; + long _streamLength; + + /// Initializes a new instance of the class. + /// The real (uncompressed) length of the stream. + /// Parameters that are used to create the base stream. + /// + public ForcedSeekStream(long length, params object[] args) + { + _streamLength = length; + _baseStream = (T)Activator.CreateInstance(typeof(T), args); + _backFile = Path.GetTempFileName(); + _backStream = new FileStream(_backFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + + if(length == 0) + CalculateLength(); + } + + /// Initializes a new instance of the class. + /// Parameters that are used to create the base stream. + /// + public ForcedSeekStream(params object[] args) + { + _baseStream = (T)Activator.CreateInstance(typeof(T), args); + _backFile = Path.GetTempFileName(); + _backStream = new FileStream(_backFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + CalculateLength(); + } + + /// + public override bool CanRead => _baseStream.CanRead; + + /// + public override bool CanSeek => true; + + /// + public override bool CanWrite => false; + + /// + public override long Length => _streamLength; + + /// + public override long Position + { + get => _backStream.Position; + + set => SetPosition(value); + } + + /// + /// Calculates the real (uncompressed) length of the stream. It basically reads (uncompresses) the whole stream to + /// memory discarding its contents, so it should be used as a last resort. + /// + /// The length. + public void CalculateLength() + { + int read; + + do + { + var buffer = new byte[BUFFER_LEN]; + read = _baseStream.EnsureRead(buffer, 0, BUFFER_LEN); + _backStream.Write(buffer, 0, read); + } while(read == BUFFER_LEN); + + _streamLength = _backStream.Length; + _backStream.Position = 0; + } + + void SetPosition(long position) + { + if(position == _backStream.Position) + return; + + if(position < _backStream.Length) + { + _backStream.Position = position; + + return; + } + + if(position > _streamLength) + position = _streamLength; + + _backStream.Position = _backStream.Length; + long toPosition = position - _backStream.Position; + var fullBufferReads = (int)(toPosition / BUFFER_LEN); + var restToRead = (int)(toPosition % BUFFER_LEN); + byte[] buffer; + int bufPos; + int left; + + for(var i = 0; i < fullBufferReads; i++) + { + buffer = new byte[BUFFER_LEN]; + bufPos = 0; + left = BUFFER_LEN; + + while(left > 0) + { + int done = _baseStream.EnsureRead(buffer, bufPos, left); + left -= done; + bufPos += done; + } + + _backStream.Write(buffer, 0, BUFFER_LEN); + } + + buffer = new byte[restToRead]; + bufPos = 0; + left = restToRead; + + while(left > 0) + { + int done = _baseStream.EnsureRead(buffer, bufPos, left); + left -= done; + bufPos += done; + } + + _backStream.Write(buffer, 0, restToRead); + } + + /// + public override void Flush() + { + _baseStream.Flush(); + _backStream.Flush(); + } + + /// + public override int Read(byte[] buffer, int offset, int count) + { + if(_backStream.Position + count > _streamLength) + count = (int)(_streamLength - _backStream.Position); + + if(_backStream.Position + count <= _backStream.Length) + return _backStream.EnsureRead(buffer, offset, count); + + long oldPosition = _backStream.Position; + SetPosition(_backStream.Position + count); + SetPosition(oldPosition); + + return _backStream.EnsureRead(buffer, offset, count); + } + + /// + public override int ReadByte() + { + if(_backStream.Position + 1 > _streamLength) + return -1; + + if(_backStream.Position + 1 <= _backStream.Length) + return _backStream.ReadByte(); + + SetPosition(_backStream.Position + 1); + SetPosition(_backStream.Position - 1); + + return _backStream.ReadByte(); + } + + /// + public override long Seek(long offset, SeekOrigin origin) + { + switch(origin) + { + case SeekOrigin.Begin: + if(offset < 0) + throw new IOException(Localization.Cannot_seek_before_stream_start); + + SetPosition(offset); + + break; + case SeekOrigin.End: + if(offset > 0) + throw new IOException(Localization.Cannot_seek_after_stream_end); + + if(_streamLength == 0) + CalculateLength(); + + SetPosition(_streamLength + offset); + + break; + default: + SetPosition(_backStream.Position + offset); + + break; + } + + return _backStream.Position; + } + + /// + public override void SetLength(long value) => throw new NotSupportedException(); + + /// + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); + + /// + public override void Close() + { + _backStream?.Close(); + File.Delete(_backFile); + } + + ~ForcedSeekStream() + { + _backStream?.Close(); + File.Delete(_backFile); + } +} \ No newline at end of file diff --git a/Aaru.Helpers/IO/NonClosableStream.cs b/Aaru.Helpers/IO/NonClosableStream.cs new file mode 100644 index 000000000..72c100df8 --- /dev/null +++ b/Aaru.Helpers/IO/NonClosableStream.cs @@ -0,0 +1,78 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : NonClosableStream.cs +// Author(s) : Natalia Portillo +// +// Component : Compression. +// +// --[ Description ] ---------------------------------------------------------- +// +// Overrides MemoryStream to ignore standard close requests. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.IO; + +namespace Aaru.Helpers.IO; + +/// +/// Creates a MemoryStream that ignores close commands +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public sealed class NonClosableStream : Stream +{ + readonly Stream _baseStream; + + public NonClosableStream(byte[] buffer) => _baseStream = new MemoryStream(buffer); + + public NonClosableStream() => _baseStream = new MemoryStream(); + + public NonClosableStream(Stream stream) => _baseStream = stream; + + public override bool CanRead => _baseStream.CanRead; + public override bool CanSeek => _baseStream.CanSeek; + public override bool CanWrite => _baseStream.CanWrite; + public override long Length => _baseStream.Length; + + public override long Position + { + get => _baseStream.Position; + set => _baseStream.Position = value; + } + + public override void Flush() => _baseStream.Flush(); + + public override int Read(byte[] buffer, int offset, int count) => _baseStream.EnsureRead(buffer, offset, count); + + public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin); + + public override void SetLength(long value) => _baseStream.SetLength(value); + + public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count); + + public override void Close() + { + // Do nothing + } + + public void ReallyClose() => _baseStream.Close(); +} \ No newline at end of file diff --git a/Aaru.Helpers/IO/OffsetStream.cs b/Aaru.Helpers/IO/OffsetStream.cs new file mode 100644 index 000000000..07fa54a2e --- /dev/null +++ b/Aaru.Helpers/IO/OffsetStream.cs @@ -0,0 +1,680 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : OffsetStream.cs +// Author(s) : Natalia Portillo +// +// Component : Filters. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides a stream that's a subset of another stream. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using Microsoft.Win32.SafeHandles; +#if !NETSTANDARD2_0 + +#endif + +namespace Aaru.Helpers.IO; + +/// Creates a stream that is a subset of another stream. +/// +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public sealed class OffsetStream : Stream +{ + readonly Stream _baseStream; + readonly long _streamEnd; + readonly long _streamStart; + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified stream, both inclusive. + /// + /// Base stream + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(Stream stream, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = stream; + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// A bitwise combination of the enumeration values that specifies additional file options. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, + FileOptions options, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(path, mode, access, share, bufferSize, options); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A file handle for the file that the stream will encapsulate. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(SafeFileHandle handle, FileAccess access, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(handle, access); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A file handle for the file that the stream will encapsulate. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(SafeFileHandle handle, FileAccess access, int bufferSize, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(handle, access, bufferSize); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A file handle for the file that the stream will encapsulate. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// Specifies whether to use asynchronous I/O or synchronous I/O. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(handle, access, bufferSize, isAsync); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// Specifies whether to use asynchronous I/O or synchronous I/O. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync, + long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(path, mode, access, share, bufferSize, useAsync); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, long start, + long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(path, mode, access, share, bufferSize); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(path, mode, access, share); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(string path, FileMode mode, FileAccess access, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(path, mode, access); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified file, both inclusive. + /// + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(string path, FileMode mode, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new FileStream(path, mode); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified byte array, both inclusive. + /// + /// The array of unsigned bytes to add at the end of this stream. + /// The index into at which the stream begins. + /// The length in bytes to add to the end of the current stream. + /// The setting of the CanWrite property, currently ignored. + /// Currently ignored. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new MemoryStream(buffer, index, count, writable, publiclyVisible); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified byte array, both inclusive. + /// + /// The array of unsigned bytes to add at the end of this stream. + /// The index into at which the stream begins. + /// The length in bytes to add to the end of the current stream. + /// The setting of the CanWrite property, currently ignored. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(byte[] buffer, int index, int count, bool writable, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new MemoryStream(buffer, index, count, writable); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified byte array, both inclusive. + /// + /// The array of unsigned bytes to add at the end of this stream. + /// The index into at which the stream begins. + /// The length in bytes to add to the end of the current stream. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(byte[] buffer, int index, int count, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new MemoryStream(buffer, index, count); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified byte array, both inclusive. + /// + /// The array of unsigned bytes to add at the end of this stream. + /// The setting of the CanWrite property, currently ignored. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(byte[] buffer, bool writable, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new MemoryStream(buffer, writable); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + /// + /// Initializes a stream that only allows reading from to of the + /// specified byte array, both inclusive. + /// + /// The array of unsigned bytes to add at the end of this stream. + /// Start position + /// Last readable position + /// Invalid range + public OffsetStream(byte[] buffer, long start, long end) + { + if(start < 0) + throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number); + + if(end < 0) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number); + + _streamStart = start; + _streamEnd = end; + + _baseStream = new MemoryStream(buffer); + + if(end > _baseStream.Length) + throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end); + + _baseStream.Position = start; + } + + /// + public override bool CanRead => _baseStream.CanRead; + + /// + public override bool CanSeek => _baseStream.CanSeek; + + /// + public override bool CanWrite => _baseStream.CanWrite; + + /// + public override long Length => _streamEnd - _streamStart + 1; + + /// + public override long Position + { + get => _baseStream.Position - _streamStart; + + set + { + if(value + _streamStart > _streamEnd) + throw new IOException(Localization.Cannot_set_position_past_stream_end); + + _baseStream.Position = value + _streamStart; + } + } + + ~OffsetStream() + { + _baseStream.Close(); + _baseStream.Dispose(); + } + + /// + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + if(_baseStream.Position + count > _streamEnd) + count = (int)(_streamEnd - _baseStream.Position); + + return _baseStream.BeginRead(buffer, offset, count, callback, state); + } + + /// + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + if(_baseStream.Position + count > _streamEnd) + throw new IOException(Localization.Cannot_write_past_stream_end); + + return _baseStream.BeginWrite(buffer, offset, count, callback, state); + } + + /// + public override void Close() => _baseStream.Close(); + + /// + public override int EndRead(IAsyncResult asyncResult) => _baseStream.EndRead(asyncResult); + + /// + public override void EndWrite(IAsyncResult asyncResult) => _baseStream.EndWrite(asyncResult); + + /// + public override int ReadByte() => _baseStream.Position == _streamEnd + 1 ? -1 : _baseStream.ReadByte(); + + /// + public override void WriteByte(byte value) + { + if(_baseStream.Position + 1 > _streamEnd) + throw new IOException(Localization.Cannot_write_past_stream_end); + + _baseStream.WriteByte(value); + } + + /// + public override void Flush() => _baseStream.Flush(); + + /// + public override int Read(byte[] buffer, int offset, int count) + { + if(_baseStream.Position + count > _streamEnd + 1) + count = (int)(_streamEnd - _baseStream.Position); + + return _baseStream.EnsureRead(buffer, offset, count); + } + + /// + public override long Seek(long offset, SeekOrigin origin) + { + switch(origin) + { + case SeekOrigin.Begin: + if(offset + _streamStart > _streamEnd) + throw new IOException(Localization.Cannot_seek_after_stream_end); + + return _baseStream.Seek(offset + _streamStart, SeekOrigin.Begin) - _streamStart; + case SeekOrigin.End: + if(offset - (_baseStream.Length - _streamEnd) < _streamStart) + throw new IOException(Localization.Cannot_seek_before_stream_start); + + return _baseStream.Seek(offset - (_baseStream.Length - _streamEnd), SeekOrigin.End) - _streamStart; + default: + if(offset + _baseStream.Position > _streamEnd) + throw new IOException(Localization.Cannot_seek_after_stream_end); + + return _baseStream.Seek(offset, SeekOrigin.Current) - _streamStart; + } + } + + /// + public override void SetLength(long value) => + throw new NotSupportedException(Localization.Growing_OffsetStream_is_not_supported); + + /// + public override void Write(byte[] buffer, int offset, int count) + { + if(_baseStream.Position + count > _streamEnd) + throw new IOException(Localization.Cannot_write_past_stream_end); + + _baseStream.Write(buffer, offset, count); + } +} \ No newline at end of file diff --git a/Aaru.Helpers/IO/SplitJoinStream.cs b/Aaru.Helpers/IO/SplitJoinStream.cs new file mode 100644 index 000000000..34981ec06 --- /dev/null +++ b/Aaru.Helpers/IO/SplitJoinStream.cs @@ -0,0 +1,372 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using Microsoft.Win32.SafeHandles; + +namespace Aaru.Helpers.IO; + +/// +/// Implements a stream that joins two or more files (sequentially) as a single stream +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public class SplitJoinStream : Stream +{ + readonly Dictionary _baseStreams; + long _position; + long _streamLength; + + /// + public SplitJoinStream() + { + _baseStreams = new Dictionary(); + _streamLength = 0; + _position = 0; + } + + /// + public override bool CanRead => true; + + /// + public override bool CanSeek => true; + + /// + public override bool CanWrite => false; + + /// + public override long Length => _streamLength; + + /// + public override long Position + { + get => _position; + + set + { + if(value >= _streamLength) + throw new IOException(Localization.Cannot_set_position_past_stream_end); + + _position = value; + } + } + + /// Adds a stream at the end of the current stream + /// Stream to add + /// The specified stream is non-readable or non-seekable + public void Add(Stream stream) + { + if(!stream.CanSeek) + throw new ArgumentException(Localization.Non_seekable_streams_are_not_supported); + + if(!stream.CanRead) + throw new ArgumentException(Localization.Non_readable_streams_are_not_supported); + + _baseStreams[_streamLength] = stream; + _streamLength += stream.Length; + } + + /// Adds the specified file to the end of the current stream + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// A bitwise combination of the enumeration values that specifies additional file options. + public void Add(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, + FileOptions options) => Add(new FileStream(path, mode, access, share, bufferSize, options)); + + /// Adds the specified file to the end of the current stream + /// A file handle for the file that the stream will encapsulate. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + public void Add(SafeFileHandle handle, FileAccess access) => Add(new FileStream(handle, access)); + + /// Adds the specified file to the end of the current stream + /// A file handle for the file that the stream will encapsulate. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + public void Add(SafeFileHandle handle, FileAccess access, int bufferSize) => + Add(new FileStream(handle, access, bufferSize)); + + /// Adds the specified file to the end of the current stream + /// A file handle for the file that the stream will encapsulate. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// Specifies whether to use asynchronous I/O or synchronous I/O. + public void Add(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) => + Add(new FileStream(handle, access, bufferSize, isAsync)); + + /// Adds the specified file to the end of the current stream + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + /// Specifies whether to use asynchronous I/O or synchronous I/O. + public void Add(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) => + Add(new FileStream(path, mode, access, share, bufferSize, useAsync)); + + /// Adds the specified file to the end of the current stream + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + /// + /// A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is + /// 4096. + /// + public void Add(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) => + Add(new FileStream(path, mode, access, share, bufferSize)); + + /// Adds the specified file to the end of the current stream + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + /// + /// A bitwise combination of the enumeration values that determines how the file will be shared by + /// processes. + /// + public void Add(string path, FileMode mode, FileAccess access, FileShare share) => + Add(new FileStream(path, mode, access, share)); + + /// Adds the specified file to the end of the current stream + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + public void Add(string path, FileMode mode, FileAccess access) => Add(new FileStream(path, mode, access)); + + /// Adds the specified file to the end of the current stream + /// A relative or absolute path for the file that the stream will encapsulate. + /// One of the enumeration values that determines how to open or create the file. + public void Add(string path, FileMode mode) => Add(new FileStream(path, mode)); + + /// Adds the specified byte array to the end of the current stream + /// The array of unsigned bytes to add at the end of this stream. + /// The index into at which the stream begins. + /// The length in bytes to add to the end of the current stream. + /// The setting of the CanWrite property, currently ignored. + /// Currently ignored. + public void Add(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) => + Add(new MemoryStream(buffer, index, count, writable, publiclyVisible)); + + /// Adds the specified byte array to the end of the current stream + /// The array of unsigned bytes to add at the end of this stream. + /// The index into at which the stream begins. + /// The length in bytes to add to the end of the current stream. + /// The setting of the CanWrite property, currently ignored. + public void Add(byte[] buffer, int index, int count, bool writable) => + Add(new MemoryStream(buffer, index, count, writable)); + + /// Adds the specified byte array to the end of the current stream + /// The array of unsigned bytes to add at the end of this stream. + /// The index into at which the stream begins. + /// The length in bytes to add to the end of the current stream. + public void Add(byte[] buffer, int index, int count) => Add(new MemoryStream(buffer, index, count)); + + /// Adds the specified byte array to the end of the current stream + /// The array of unsigned bytes to add at the end of this stream. + /// The setting of the CanWrite property, currently ignored. + public void Add(byte[] buffer, bool writable) => Add(new MemoryStream(buffer, writable)); + + /// Adds the specified byte array to the end of the current stream + /// The array of unsigned bytes to add at the end of this stream. + public void Add(byte[] buffer) => Add(new MemoryStream(buffer)); + + /// Adds a range of files to the end of the current stream, alphabetically sorted + /// Base file path, directory path only + /// Counter format, includes filename and a formatting string + /// Counter start, defaults to 0 + /// + /// A bitwise combination of the enumeration values that determines how the file can be accessed by a + /// object. + /// + public void AddRange(string basePath, string counterFormat = "{0:D3}", int counterStart = 0, + FileAccess access = FileAccess.Read) + { + while(true) + { + string filePath = Path.Combine(basePath, string.Format(counterFormat, counterStart)); + + if(!File.Exists(filePath)) + break; + + Add(filePath, FileMode.Open, access); + + counterStart++; + } + } + + ~SplitJoinStream() + { + foreach(Stream stream in _baseStreams.Values) + { + stream.Close(); + stream.Dispose(); + } + + _baseStreams.Clear(); + _position = 0; + } + + /// + public override IAsyncResult + BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) => + throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported); + + /// + public override IAsyncResult + BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) => + throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported); + + /// + public override void Close() + { + foreach(Stream stream in _baseStreams.Values) + stream.Close(); + + _baseStreams.Clear(); + _position = 0; + } + + /// + public override int EndRead(IAsyncResult asyncResult) => + throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported); + + /// + public override void EndWrite(IAsyncResult asyncResult) => + throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported); + + /// + public override int ReadByte() + { + if(_position >= _streamLength) + return -1; + + KeyValuePair baseStream = _baseStreams.FirstOrDefault(s => s.Key >= _position); + + if(baseStream.Value == null) + return -1; + + baseStream.Value.Position = _position - baseStream.Key; + _position++; + + return baseStream.Value.ReadByte(); + } + + /// + public override void WriteByte(byte value) => throw new ReadOnlyException(Localization.This_stream_is_read_only); + + /// + public override void Flush() {} + + /// + public override int Read(byte[] buffer, int offset, int count) + { + var read = 0; + + while(count > 0) + { + KeyValuePair baseStream = _baseStreams.LastOrDefault(s => s.Key <= _position); + + if(baseStream.Value == null) + break; + + baseStream.Value.Position = _position - baseStream.Key; + + int currentCount = count; + + if(baseStream.Value.Position + currentCount > baseStream.Value.Length) + currentCount = (int)(baseStream.Value.Length - baseStream.Value.Position); + + read += baseStream.Value.Read(buffer, offset, currentCount); + + count -= currentCount; + offset += currentCount; + } + + return read; + } + + /// + public override long Seek(long offset, SeekOrigin origin) + { + switch(origin) + { + case SeekOrigin.Begin: + if(offset >= _streamLength) + throw new IOException(Localization.Cannot_seek_after_stream_end); + + _position = offset; + + break; + case SeekOrigin.End: + if(_position - offset < 0) + throw new IOException(Localization.Cannot_seek_before_stream_start); + + _position -= offset; + + break; + default: + if(_position + offset >= _streamLength) + throw new IOException(Localization.Cannot_seek_after_stream_end); + + _position += offset; + + break; + } + + return _position; + } + + /// + public override void SetLength(long value) => throw new ReadOnlyException(Localization.This_stream_is_read_only); + + /// + public override void Write(byte[] buffer, int offset, int count) => + throw new ReadOnlyException(Localization.This_stream_is_read_only); +} \ No newline at end of file diff --git a/Aaru.Helpers/Localization/Localization.Designer.cs b/Aaru.Helpers/Localization/Localization.Designer.cs new file mode 100644 index 000000000..36a0e6131 --- /dev/null +++ b/Aaru.Helpers/Localization/Localization.Designer.cs @@ -0,0 +1,197 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Aaru.Helpers { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Localization { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Localization() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Aaru.Helpers.Localization.Localization", typeof(Localization).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Asynchronous I/O is not supported.. + /// + internal static string Asynchronous_IO_is_not_supported { + get { + return ResourceManager.GetString("Asynchronous_IO_is_not_supported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot read past stream end.. + /// + internal static string Cannot_read_past_stream_end { + get { + return ResourceManager.GetString("Cannot_read_past_stream_end", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot seek after stream end.. + /// + internal static string Cannot_seek_after_stream_end { + get { + return ResourceManager.GetString("Cannot_seek_after_stream_end", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot seek before stream start.. + /// + internal static string Cannot_seek_before_stream_start { + get { + return ResourceManager.GetString("Cannot_seek_before_stream_start", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set position past stream end.. + /// + internal static string Cannot_set_position_past_stream_end { + get { + return ResourceManager.GetString("Cannot_set_position_past_stream_end", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot write past stream end.. + /// + internal static string Cannot_write_past_stream_end { + get { + return ResourceManager.GetString("Cannot_write_past_stream_end", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to End can't be a negative number.. + /// + internal static string End_cant_be_a_negative_number { + get { + return ResourceManager.GetString("End_cant_be_a_negative_number", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to End is after stream end.. + /// + internal static string End_is_after_stream_end { + get { + return ResourceManager.GetString("End_is_after_stream_end", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Growing OffsetStream is not supported.. + /// + internal static string Growing_OffsetStream_is_not_supported { + get { + return ResourceManager.GetString("Growing_OffsetStream_is_not_supported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Length of value array must not be more than length of destination. + /// + internal static string Length_of_value_array_must_not_be_more_than_length_of_destination { + get { + return ResourceManager.GetString("Length_of_value_array_must_not_be_more_than_length_of_destination", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Non-readable streams are not supported. + /// + internal static string Non_readable_streams_are_not_supported { + get { + return ResourceManager.GetString("Non_readable_streams_are_not_supported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Non-seekable streams are not supported. + /// + internal static string Non_seekable_streams_are_not_supported { + get { + return ResourceManager.GetString("Non_seekable_streams_are_not_supported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offset. + /// + internal static string Offset { + get { + return ResourceManager.GetString("Offset", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start can't be a negative number.. + /// + internal static string Start_cant_be_a_negative_number { + get { + return ResourceManager.GetString("Start_cant_be_a_negative_number", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This stream is read-only. + /// + internal static string This_stream_is_read_only { + get { + return ResourceManager.GetString("This_stream_is_read_only", resourceCulture); + } + } + } +} diff --git a/Aaru.Helpers/Localization/Localization.es.resx b/Aaru.Helpers/Localization/Localization.es.resx new file mode 100644 index 000000000..9ed14ff70 --- /dev/null +++ b/Aaru.Helpers/Localization/Localization.es.resx @@ -0,0 +1,64 @@ + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + Compensación + + + La longitud de una colección no puede ser mayor que la longitud del destino + + + Las secuencias no legíbles no están soportadas. + + + Las secuencias no posicionables no están soportadas. + + + No se puede leer más allá del final de la secuencia. + + + No se puede posicionar después del final de la secuencia. + + + No se puede posicionar antes del comienzo de la secuencia. + + + No se puede establecer la posición más allá del final de la secuencia. + + + No se puede escribir después del final de la secuencia. + + + El final no puede ser un número negativo. + + + El final está después del final de la secuencia. + + + No se puede agrandar un OffsetStream. + + + E/S asíncrona no soportada. + + + El comienzo no puede ser un número negativo. + + + Esta secuencia es de sólo lectura. + + \ No newline at end of file diff --git a/Aaru.Helpers/Localization/Localization.resx b/Aaru.Helpers/Localization/Localization.resx new file mode 100644 index 000000000..6f9a16a67 --- /dev/null +++ b/Aaru.Helpers/Localization/Localization.resx @@ -0,0 +1,71 @@ + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + Length of value array must not be more than length of destination + + + Offset + + + Start can't be a negative number. + + + End can't be a negative number. + + + End is after stream end. + + + Cannot set position past stream end. + + + Cannot read past stream end. + + + Cannot write past stream end. + + + Growing OffsetStream is not supported. + + + Cannot seek before stream start. + + + Cannot seek after stream end. + + + Non-seekable streams are not supported + + + Non-readable streams are not supported + + + Asynchronous I/O is not supported. + + + This stream is read-only + + \ No newline at end of file diff --git a/Aaru.Helpers/Marshal.cs b/Aaru.Helpers/Marshal.cs new file mode 100644 index 000000000..738c75f7c --- /dev/null +++ b/Aaru.Helpers/Marshal.cs @@ -0,0 +1,492 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Marshal.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides marshalling for binary data. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Aaru.Helpers; + +/// Provides methods to marshal binary data into C# structs +[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public static class Marshal +{ + /// Returns the size of an unmanaged type in bytes. + /// The type whose size is to be returned. + /// The size, in bytes, of the type that is specified by the generic type parameter. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SizeOf() => System.Runtime.InteropServices.Marshal.SizeOf(); + + /// Marshal little-endian binary data to a structure + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureLittleEndian(byte[] bytes) where T : struct + { + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + + var str = (T)(System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)) ?? + default(T)); + + ptr.Free(); + + return str; + } + + /// Marshal little-endian binary data to a structure + /// Byte array containing the binary data + /// Start on the array where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureLittleEndian(byte[] bytes, int start, int length) where T : struct + { + Span span = bytes; + + return ByteArrayToStructureLittleEndian(span.Slice(start, length).ToArray()); + } + + /// Marshal big-endian binary data to a structure + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureBigEndian(byte[] bytes) where T : struct + { + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + + object str = (T)(System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)) ?? + default(T)); + + ptr.Free(); + + return (T)SwapStructureMembersEndian(str); + } + + /// Marshal big-endian binary data to a structure + /// Byte array containing the binary data + /// Start on the array where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureBigEndian(byte[] bytes, int start, int length) where T : struct + { + Span span = bytes; + + return ByteArrayToStructureBigEndian(span.Slice(start, length).ToArray()); + } + + /// Marshal PDP-11 binary data to a structure + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructurePdpEndian(byte[] bytes) where T : struct + { + { + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + + object str = + (T)(System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)) ?? + default(T)); + + ptr.Free(); + + return (T)SwapStructureMembersEndianPdp(str); + } + } + + /// Marshal PDP-11 binary data to a structure + /// Byte array containing the binary data + /// Start on the array where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructurePdpEndian(byte[] bytes, int start, int length) where T : struct + { + Span span = bytes; + + return ByteArrayToStructurePdpEndian(span.Slice(start, length).ToArray()); + } + + /// + /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this + /// method will crash. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureLittleEndian(ReadOnlySpan bytes) where T : struct => + MemoryMarshal.Read(bytes); + + /// + /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this + /// method will crash. + /// + /// Byte span containing the binary data + /// Start on the span where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureLittleEndian(ReadOnlySpan bytes, int start, int length) where T : struct => + MemoryMarshal.Read(bytes.Slice(start, length)); + + /// + /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method + /// will crash. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureBigEndian(ReadOnlySpan bytes) where T : struct + { + T str = SpanToStructureLittleEndian(bytes); + + return (T)SwapStructureMembersEndian(str); + } + + /// + /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method + /// will crash. + /// + /// Byte span containing the binary data + /// Start on the span where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureBigEndian(ReadOnlySpan bytes, int start, int length) where T : struct + { + T str = SpanToStructureLittleEndian(bytes.Slice(start, length)); + + return (T)SwapStructureMembersEndian(str); + } + + /// + /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will + /// crash. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructurePdpEndian(ReadOnlySpan bytes) where T : struct + { + object str = SpanToStructureLittleEndian(bytes); + + return (T)SwapStructureMembersEndianPdp(str); + } + + /// + /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will + /// crash. + /// + /// Byte array containing the binary data + /// Start on the span where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructurePdpEndian(ReadOnlySpan bytes, int start, int length) where T : struct + { + object str = SpanToStructureLittleEndian(bytes.Slice(start, length)); + + return (T)SwapStructureMembersEndianPdp(str); + } + + /// + /// Marshal a structure depending on the decoration of . If the + /// decoration is not present it will marshal as a reference type containing little endian structure. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + /// + /// The contains an unsupported + /// endian + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MarshalStructure(byte[] bytes) where T : struct + { + if(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is not MarshallingPropertiesAttribute + properties) + return ByteArrayToStructureLittleEndian(bytes); + + return properties.Endian switch + { + BitEndian.Little => properties.HasReferences + ? ByteArrayToStructureLittleEndian(bytes) + : SpanToStructureLittleEndian(bytes), + BitEndian.Big => properties.HasReferences + ? ByteArrayToStructureBigEndian(bytes) + : SpanToStructureBigEndian(bytes), + BitEndian.Pdp => properties.HasReferences + ? ByteArrayToStructurePdpEndian(bytes) + : SpanToStructurePdpEndian(bytes), + _ => throw new ArgumentOutOfRangeException() + }; + } + + /// Swaps all members of a structure + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public static object SwapStructureMembersEndian(object str) + { + Type t = str.GetType(); + FieldInfo[] fieldInfo = t.GetFields(); + + foreach(FieldInfo fi in fieldInfo) + { + if(fi.FieldType == typeof(short) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short)) + { + var x = (short)(fi.GetValue(str) ?? default(short)); + fi.SetValue(str, (short)(x << 8 | x >> 8 & 0xFF)); + } + else if(fi.FieldType == typeof(int) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)) + { + var x = (int)(fi.GetValue(str) ?? default(int)); + x = (int)(x << 8 & 0xFF00FF00 | (uint)x >> 8 & 0xFF00FF); + fi.SetValue(str, (int)((uint)x << 16 | (uint)x >> 16 & 0xFFFF)); + } + else if(fi.FieldType == typeof(long) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long)) + { + var x = (long)(fi.GetValue(str) ?? default(long)); + x = (x & 0x00000000FFFFFFFF) << 32 | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32); + x = (x & 0x0000FFFF0000FFFF) << 16 | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16); + x = (x & 0x00FF00FF00FF00FF) << 8 | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8); + + fi.SetValue(str, x); + } + else if(fi.FieldType == typeof(ushort) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort)) + { + var x = (ushort)(fi.GetValue(str) ?? default(ushort)); + fi.SetValue(str, (ushort)(x << 8 | x >> 8)); + } + else if(fi.FieldType == typeof(uint) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)) + { + var x = (uint)(fi.GetValue(str) ?? default(uint)); + x = x << 8 & 0xFF00FF00 | x >> 8 & 0xFF00FF; + fi.SetValue(str, x << 16 | x >> 16); + } + else if(fi.FieldType == typeof(ulong) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong)) + { + var x = (ulong)(fi.GetValue(str) ?? default(ulong)); + x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; + x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; + x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; + fi.SetValue(str, x); + } + else if(fi.FieldType == typeof(float)) + { + var flt = (float)(fi.GetValue(str) ?? default(float)); + byte[] flt_b = BitConverter.GetBytes(flt); + + fi.SetValue(str, BitConverter.ToSingle(new[] + { + flt_b[3], flt_b[2], flt_b[1], flt_b[0] + }, 0)); + } + else if(fi.FieldType == typeof(double)) + { + var dbl = (double)(fi.GetValue(str) ?? default(double)); + byte[] dbl_b = BitConverter.GetBytes(dbl); + + fi.SetValue(str, BitConverter.ToDouble(new[] + { + dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0] + }, 0)); + } + else if(fi.FieldType == typeof(byte) || fi.FieldType == typeof(sbyte)) + { + // Do nothing, can't byteswap them! + } + else if(fi.FieldType == typeof(Guid)) + { + // TODO: Swap GUID + } + + // TODO: Swap arrays + else if(fi.FieldType.IsValueType && fi.FieldType is { IsEnum: false, IsArray: false }) + { + object obj = fi.GetValue(str); + object strc = SwapStructureMembersEndian(obj); + fi.SetValue(str, strc); + } + } + + return str; + } + + /// Swaps all fields in an structure considering them to follow PDP endian conventions + /// Source structure + /// Resulting structure + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static object SwapStructureMembersEndianPdp(object str) + { + Type t = str.GetType(); + FieldInfo[] fieldInfo = t.GetFields(); + + foreach(FieldInfo fi in fieldInfo) + { + if(fi.FieldType == typeof(short) || + fi.FieldType == typeof(long) || + fi.FieldType == typeof(ushort) || + fi.FieldType == typeof(ulong) || + fi.FieldType == typeof(float) || + fi.FieldType == typeof(double) || + fi.FieldType == typeof(byte) || + fi.FieldType == typeof(sbyte) || + fi.FieldType == typeof(Guid)) + { + // Do nothing + } + else if(fi.FieldType == typeof(int) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int)) + { + var x = (int)(fi.GetValue(str) ?? default(int)); + fi.SetValue(str, (x & 0xffffu) << 16 | (x & 0xffff0000u) >> 16); + } + else if(fi.FieldType == typeof(uint) || + fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint)) + { + var x = (uint)(fi.GetValue(str) ?? default(uint)); + fi.SetValue(str, (x & 0xffffu) << 16 | (x & 0xffff0000u) >> 16); + } + + // TODO: Swap arrays + else if(fi.FieldType.IsValueType && fi.FieldType is { IsEnum: false, IsArray: false }) + { + object obj = fi.GetValue(str); + object strc = SwapStructureMembersEndianPdp(obj); + fi.SetValue(str, strc); + } + } + + return str; + } + + /// Marshal a structure to little-endian binary data + /// The structure you want to marshal to binary + /// Type of the structure to marshal + /// The byte array representing the given structure + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] StructureToByteArrayLittleEndian(T str) where T : struct + { + var buf = new byte[SizeOf()]; + var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned); + System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false); + ptr.Free(); + + return buf; + } + + /// Marshal a structure to little-endian binary data + /// The structure you want to marshal to binary + /// Type of the structure to marshal + /// The byte array representing the given structure + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] StructureToByteArrayBigEndian(T str) where T : struct => + StructureToByteArrayLittleEndian((T)SwapStructureMembersEndian(str)); + + /// Converts a hexadecimal string into a byte array + /// Hexadecimal string + /// Resulting byte array + /// Number of output bytes processed + public static int ConvertFromHexAscii(string hex, out byte[] outBuf) + { + outBuf = null; + + if(hex is null or "") + return -1; + + var off = 0; + + if(hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) + off = 2; + + outBuf = new byte[(hex.Length - off) / 2]; + var count = 0; + + for(int i = off; i < hex.Length; i += 2) + { + char c = hex[i]; + + if(c is < '0' or > '9' and < 'A' or > 'F' and < 'a' or > 'f') + break; + + c -= c switch + { + >= 'a' and <= 'f' => '\u0057', + >= 'A' and <= 'F' => '\u0037', + _ => '\u0030' + }; + + outBuf[(i - off) / 2] = (byte)(c << 4); + + c = hex[i + 1]; + + if(c is < '0' or > '9' and < 'A' or > 'F' and < 'a' or > 'f') + break; + + c -= c switch + { + >= 'a' and <= 'f' => '\u0057', + >= 'A' and <= 'F' => '\u0037', + _ => '\u0030' + }; + + outBuf[(i - off) / 2] += (byte)c; + + count++; + } + + return count; + } +} \ No newline at end of file diff --git a/Aaru.Helpers/MarshallingPropertiesAttribute.cs b/Aaru.Helpers/MarshallingPropertiesAttribute.cs new file mode 100644 index 000000000..40dc5d63f --- /dev/null +++ b/Aaru.Helpers/MarshallingPropertiesAttribute.cs @@ -0,0 +1,62 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : MarshallingPropertiesAttribute.cs +// Author(s) : Natalia Portillo +// +// Component : Common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Declares properties of structs for marshalling. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; + +namespace Aaru.Helpers; + +/// +/// Defines properties to help marshalling structs from binary data +[AttributeUsage(AttributeTargets.Struct)] +public sealed class MarshallingPropertiesAttribute : Attribute +{ + /// + /// Defines properties to help marshalling structs from binary data + /// Defines properties to help marshalling structs from binary data + public MarshallingPropertiesAttribute(BitEndian endian) + { + Endian = endian; + HasReferences = true; + } + + /// c + public BitEndian Endian { get; } + + /// Tells if the structure, or any nested structure, has any non-value type (e.g. arrays, strings, etc). + public bool HasReferences { get; set; } +} \ No newline at end of file diff --git a/Aaru.Helpers/PrintHex.cs b/Aaru.Helpers/PrintHex.cs new file mode 100644 index 000000000..0f3c92b87 --- /dev/null +++ b/Aaru.Helpers/PrintHex.cs @@ -0,0 +1,139 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : PrintHex.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Prints a byte array as hexadecimal. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Text; +using Aaru.Console; + +namespace Aaru.Helpers; + +/// Helper operations to get hexadecimal representations of byte arrays +public static class PrintHex +{ + /// Prints a byte array as hexadecimal values to the console + /// Array + /// Width of line + public static void PrintHexArray(byte[] array, int width = 16) => + AaruConsole.WriteLine(ByteArrayToHexArrayString(array, width)); + + /// Prints a byte array as hexadecimal values to a string + /// Array + /// Width of line + /// Use ANSI escape colors for sections + /// String containing hexadecimal values + public static string ByteArrayToHexArrayString(byte[] array, int width = 16, bool color = false) + { + if(array is null) + return null; + + // TODO: Color list + // TODO: Allow to change width + string str = Localization.Offset; + int rows = array.Length / width; + int last = array.Length % width; + int offsetLength = $"{array.Length:X}".Length; + var sb = new StringBuilder(); + + switch(last) + { + case > 0: + rows++; + + break; + case 0: + last = width; + + break; + } + + if(offsetLength < str.Length) + offsetLength = str.Length; + + while(str.Length < offsetLength) + str += ' '; + + if(color) + sb.Append("\u001b[36m"); + + sb.Append(str); + sb.Append(" "); + + for(var i = 0; i < width; i++) + sb.Append($" {i:X2}"); + + if(color) + sb.Append("\u001b[0m"); + + sb.AppendLine(); + + var b = 0; + + var format = $"{{0:X{offsetLength}}}"; + + for(var i = 0; i < rows; i++) + { + if(color) + sb.Append("\u001b[36m"); + + sb.AppendFormat(format, b); + + if(color) + sb.Append("\u001b[0m"); + + sb.Append(" "); + int lastBytes = i == rows - 1 ? last : width; + int lastSpaces = width - lastBytes; + + for(var j = 0; j < lastBytes; j++) + { + sb.Append($" {array[b]:X2}"); + b++; + } + + for(var j = 0; j < lastSpaces; j++) + sb.Append(" "); + + b -= lastBytes; + sb.Append(" "); + + for(var j = 0; j < lastBytes; j++) + { + int v = array[b]; + sb.Append(v is > 31 and < 127 or > 159 ? (char)v : '.'); + b++; + } + + sb.AppendLine(); + } + + return sb.ToString(); + } +} \ No newline at end of file diff --git a/Aaru.Helpers/StringHandlers.cs b/Aaru.Helpers/StringHandlers.cs new file mode 100644 index 000000000..07348633b --- /dev/null +++ b/Aaru.Helpers/StringHandlers.cs @@ -0,0 +1,187 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : StringHandlers.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Convert byte arrays to C# strings. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Helpers; + +/// Helper operations to work with strings +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public static class StringHandlers +{ + /// Converts a null-terminated (aka C string) ASCII byte array to a C# string + /// The corresponding C# string + /// A null-terminated (aka C string) ASCII byte array + public static string CToString(byte[] cString) => CToString(cString, Encoding.ASCII); + + /// Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string + /// The corresponding C# string + /// A null-terminated (aka C string) byte array in the specified encoding + /// Encoding. + /// Set if encoding uses 16-bit characters. + /// Start decoding at this position + public static string CToString(byte[] cString, Encoding encoding, bool twoBytes = false, int start = 0) + { + if(cString == null) + return null; + + var len = 0; + + for(int i = start; i < cString.Length; i++) + { + if(cString[i] == 0) + { + if(twoBytes) + { + if(i + 1 < cString.Length && cString[i + 1] == 0) + { + len++; + + break; + } + } + else + break; + } + + len++; + } + + if(twoBytes && len % 2 > 0) + len--; + + var dest = new byte[len]; + Array.Copy(cString, start, dest, 0, len); + + return len == 0 ? "" : encoding.GetString(dest); + } + + /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string + /// The corresponding C# string + /// A length-prefixed (aka Pascal string) ASCII byte array + public static string PascalToString(byte[] pascalString) => PascalToString(pascalString, Encoding.ASCII); + + /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string + /// The corresponding C# string + /// A length-prefixed (aka Pascal string) ASCII byte array + /// Encoding. + /// Start decoding at this position + public static string PascalToString(byte[] pascalString, Encoding encoding, int start = 0) + { + if(pascalString == null) + return null; + + byte length = pascalString[start]; + var len = 0; + + for(int i = start + 1; i < length + 1 && i < pascalString.Length; i++) + { + if(pascalString[i] == 0) + break; + + len++; + } + + var dest = new byte[len]; + Array.Copy(pascalString, start + 1, dest, 0, len); + + return len == 0 ? "" : encoding.GetString(dest); + } + + /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string + /// The corresponding C# string + /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array + public static string SpacePaddedToString(byte[] spacePaddedString) => + SpacePaddedToString(spacePaddedString, Encoding.ASCII); + + /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string + /// The corresponding C# string + /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array + /// Encoding. + /// Start decoding at this position + public static string SpacePaddedToString(byte[] spacePaddedString, Encoding encoding, int start = 0) + { + if(spacePaddedString == null) + return null; + + int len = start; + + for(int i = spacePaddedString.Length; i >= start; i--) + { + if(i == start) + return ""; + + if(spacePaddedString[i - 1] == 0x20) + continue; + + len = i; + + break; + } + + return len == 0 ? "" : encoding.GetString(spacePaddedString, start, len); + } + + /// Converts an OSTA compressed unicode byte array to a C# string + /// The C# string. + /// OSTA compressed unicode byte array. + public static string DecompressUnicode(byte[] dstring) + { + byte compId = dstring[0]; + var temp = ""; + + if(compId != 8 && compId != 16) + return null; + + for(var byteIndex = 1; byteIndex < dstring.Length;) + { + ushort unicode; + + if(compId == 16) + unicode = (ushort)(dstring[byteIndex++] << 8); + else + unicode = 0; + + if(byteIndex < dstring.Length) + unicode |= dstring[byteIndex++]; + + if(unicode == 0) + break; + + temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode)); + } + + return temp; + } +} \ No newline at end of file diff --git a/Aaru.Helpers/Swapping.cs b/Aaru.Helpers/Swapping.cs new file mode 100644 index 000000000..e5f3b64f2 --- /dev/null +++ b/Aaru.Helpers/Swapping.cs @@ -0,0 +1,113 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Swapping.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Byte-swapping methods. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Aaru.Helpers; + +/// Helper operations to work with swapping endians +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public static class Swapping +{ + /// Gets the PDP endian equivalent of the given little endian unsigned integer + /// Little endian unsigned integer + /// PDP unsigned integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint PDPFromLittleEndian(uint x) => (x & 0xffff) << 16 | (x & 0xffff0000) >> 16; + + /// Gets the PDP endian equivalent of the given big endian unsigned integer + /// Big endian unsigned integer + /// PDP unsigned integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint PDPFromBigEndian(uint x) => (x & 0xff00ff) << 8 | (x & 0xff00ff00) >> 8; + + /// Swaps the endian of the specified unsigned short integer + /// Unsigned short integer + /// Swapped unsigned short integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ushort Swap(ushort x) => (ushort)(x << 8 | x >> 8); + + /// Swaps the endian of the specified signed short integer + /// Signed short integer + /// Swapped signed short integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static short Swap(short x) => (short)(x << 8 | x >> 8 & 0xFF); + + /// Swaps the endian of the specified unsigned integer + /// Unsigned integer + /// Swapped unsigned integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint Swap(uint x) + { + x = x << 8 & 0xFF00FF00 | x >> 8 & 0xFF00FF; + + return x << 16 | x >> 16; + } + + /// Swaps the endian of the specified signed integer + /// Signed integer + /// Swapped signed integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Swap(int x) + { + x = (int)(x << 8 & 0xFF00FF00 | (uint)x >> 8 & 0xFF00FF); + + return (int)((uint)x << 16 | (uint)x >> 16 & 0xFFFF); + } + + /// Swaps the endian of the specified unsigned long integer + /// Unsigned long integer + /// Swapped unsigned long integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong Swap(ulong x) + { + x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; + x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; + x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; + + return x; + } + + /// Swaps the endian of the specified signed long integer + /// Signed long integer + /// Swapped signed long integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Swap(long x) + { + x = (x & 0x00000000FFFFFFFF) << 32 | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32); + x = (x & 0x0000FFFF0000FFFF) << 16 | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16); + x = (x & 0x00FF00FF00FF00FF) << 8 | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8); + + return x; + } +} \ No newline at end of file