omnizip 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +754 -0
- data/COPYING +502 -0
- data/Gemfile +17 -0
- data/LICENSE +12 -0
- data/README.adoc +1045 -0
- data/Rakefile +12 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +91 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +271 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +185 -0
- data/docs/getting-started/your-first-archive.adoc +218 -0
- data/docs/guides/advanced-features/encryption.adoc +300 -0
- data/docs/guides/advanced-features/index.adoc +49 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
- data/docs/guides/advanced-features/streaming.adoc +212 -0
- data/docs/guides/archive-formats/gzip-format.adoc +107 -0
- data/docs/guides/archive-formats/index.adoc +130 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
- data/docs/guides/compression-algorithms/deflate.adoc +319 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +398 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
- data/docs/guides/creating-archives.adoc +354 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +218 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +188 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/troubleshooting/index.adoc +208 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +130 -0
- data/lib/omnizip/algorithm_registry.rb +86 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
- data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
- data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
- data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
- data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
- data/lib/omnizip/algorithms/bzip2.rb +130 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
- data/lib/omnizip/algorithms/deflate.rb +128 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
- data/lib/omnizip/algorithms/deflate64.rb +109 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
- data/lib/omnizip/algorithms/lzma.rb +238 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +141 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +116 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +82 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
- data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
- data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
- data/lib/omnizip/algorithms/zstandard.rb +138 -0
- data/lib/omnizip/buffer/memory_archive.rb +251 -0
- data/lib/omnizip/buffer/memory_extractor.rb +224 -0
- data/lib/omnizip/buffer.rb +176 -0
- data/lib/omnizip/checksum_registry.rb +114 -0
- data/lib/omnizip/checksums/crc32.rb +100 -0
- data/lib/omnizip/checksums/crc64.rb +101 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/verifier.rb +131 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +120 -0
- data/lib/omnizip/chunked.rb +129 -0
- data/lib/omnizip/cli/output_formatter.rb +104 -0
- data/lib/omnizip/cli.rb +572 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +427 -0
- data/lib/omnizip/commands/archive_extract_command.rb +272 -0
- data/lib/omnizip/commands/archive_list_command.rb +218 -0
- data/lib/omnizip/commands/archive_repair_command.rb +131 -0
- data/lib/omnizip/commands/archive_verify_command.rb +117 -0
- data/lib/omnizip/commands/compress_command.rb +117 -0
- data/lib/omnizip/commands/decompress_command.rb +120 -0
- data/lib/omnizip/commands/list_command.rb +53 -0
- data/lib/omnizip/commands/metadata_command.rb +153 -0
- data/lib/omnizip/commands/parity_create_command.rb +122 -0
- data/lib/omnizip/commands/parity_repair_command.rb +122 -0
- data/lib/omnizip/commands/parity_verify_command.rb +124 -0
- data/lib/omnizip/commands/profile_list_command.rb +56 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/convenience.rb +359 -0
- data/lib/omnizip/converter/conversion_registry.rb +49 -0
- data/lib/omnizip/converter/conversion_strategy.rb +121 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
- data/lib/omnizip/converter.rb +105 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/error.rb +106 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +63 -0
- data/lib/omnizip/extraction/filter_chain.rb +177 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +240 -0
- data/lib/omnizip/extraction.rb +111 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +113 -0
- data/lib/omnizip/filter.rb +139 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +166 -0
- data/lib/omnizip/filters/bcj.rb +279 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
- data/lib/omnizip/filters/bcj2.rb +99 -0
- data/lib/omnizip/filters/bcj_arm.rb +176 -0
- data/lib/omnizip/filters/bcj_arm64.rb +244 -0
- data/lib/omnizip/filters/bcj_ia64.rb +196 -0
- data/lib/omnizip/filters/bcj_ppc.rb +190 -0
- data/lib/omnizip/filters/bcj_sparc.rb +176 -0
- data/lib/omnizip/filters/bcj_x86.rb +193 -0
- data/lib/omnizip/filters/delta.rb +196 -0
- data/lib/omnizip/filters/filter_base.rb +72 -0
- data/lib/omnizip/filters/registry.rb +123 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/format_detector.rb +162 -0
- data/lib/omnizip/format_registry.rb +59 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +172 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +385 -0
- data/lib/omnizip/formats/cpio/reader.rb +196 -0
- data/lib/omnizip/formats/cpio/writer.rb +234 -0
- data/lib/omnizip/formats/cpio.rb +140 -0
- data/lib/omnizip/formats/format_spec_loader.rb +230 -0
- data/lib/omnizip/formats/gzip.rb +238 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
- data/lib/omnizip/formats/iso/directory_record.rb +152 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +197 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +530 -0
- data/lib/omnizip/formats/iso.rb +140 -0
- data/lib/omnizip/formats/lzip.rb +175 -0
- data/lib/omnizip/formats/lzma_alone.rb +171 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
- data/lib/omnizip/formats/rar/block_parser.rb +243 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +82 -0
- data/lib/omnizip/formats/rar/decompressor.rb +238 -0
- data/lib/omnizip/formats/rar/external_writer.rb +312 -0
- data/lib/omnizip/formats/rar/header.rb +192 -0
- data/lib/omnizip/formats/rar/license_validator.rb +109 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
- data/lib/omnizip/formats/rar/reader.rb +366 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
- data/lib/omnizip/formats/rar/writer.rb +431 -0
- data/lib/omnizip/formats/rar.rb +205 -0
- data/lib/omnizip/formats/rar3/compressor.rb +73 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar3/reader.rb +386 -0
- data/lib/omnizip/formats/rar3/writer.rb +219 -0
- data/lib/omnizip/formats/rar5/compressor.rb +73 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar5/reader.rb +342 -0
- data/lib/omnizip/formats/rar5/writer.rb +214 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
- data/lib/omnizip/formats/seven_zip/header.rb +106 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
- data/lib/omnizip/formats/seven_zip.rb +93 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +94 -0
- data/lib/omnizip/formats/tar/header.rb +168 -0
- data/lib/omnizip/formats/tar/reader.rb +121 -0
- data/lib/omnizip/formats/tar/writer.rb +216 -0
- data/lib/omnizip/formats/tar.rb +84 -0
- data/lib/omnizip/formats/xz/reader.rb +116 -0
- data/lib/omnizip/formats/xz.rb +237 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
- data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
- data/lib/omnizip/formats/zip/reader.rb +250 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +375 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
- data/lib/omnizip/io/buffered_input.rb +146 -0
- data/lib/omnizip/io/buffered_output.rb +105 -0
- data/lib/omnizip/io/stream_manager.rb +115 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +124 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +146 -0
- data/lib/omnizip/metadata/metadata_editor.rb +171 -0
- data/lib/omnizip/metadata/metadata_registry.rb +64 -0
- data/lib/omnizip/metadata/metadata_validator.rb +99 -0
- data/lib/omnizip/metadata.rb +57 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +73 -0
- data/lib/omnizip/models/compression_options.rb +71 -0
- data/lib/omnizip/models/conversion_options.rb +87 -0
- data/lib/omnizip/models/conversion_result.rb +135 -0
- data/lib/omnizip/models/eta_result.rb +46 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +144 -0
- data/lib/omnizip/models/filter_config.rb +183 -0
- data/lib/omnizip/models/match_result.rb +124 -0
- data/lib/omnizip/models/optimization_suggestion.rb +91 -0
- data/lib/omnizip/models/parallel_options.rb +104 -0
- data/lib/omnizip/models/performance_result.rb +79 -0
- data/lib/omnizip/models/profile_report.rb +82 -0
- data/lib/omnizip/models/progress_options.rb +38 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +81 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +203 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
- data/lib/omnizip/parallel/worker_pool.rb +223 -0
- data/lib/omnizip/parallel.rb +149 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +73 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
- data/lib/omnizip/parity/models/main_packet.rb +128 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +109 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
- data/lib/omnizip/parity/par2_creator.rb +531 -0
- data/lib/omnizip/parity/par2_repairer.rb +407 -0
- data/lib/omnizip/parity/par2_verifier.rb +364 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
- data/lib/omnizip/parity.rb +186 -0
- data/lib/omnizip/password/encryption_registry.rb +65 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
- data/lib/omnizip/password.rb +87 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
- data/lib/omnizip/pipe.rb +121 -0
- data/lib/omnizip/platform/ntfs_streams.rb +201 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +39 -0
- data/lib/omnizip/profile/balanced_profile.rb +33 -0
- data/lib/omnizip/profile/binary_profile.rb +36 -0
- data/lib/omnizip/profile/compression_profile.rb +158 -0
- data/lib/omnizip/profile/custom_profile.rb +157 -0
- data/lib/omnizip/profile/fast_profile.rb +33 -0
- data/lib/omnizip/profile/maximum_profile.rb +33 -0
- data/lib/omnizip/profile/profile_detector.rb +110 -0
- data/lib/omnizip/profile/profile_registry.rb +161 -0
- data/lib/omnizip/profile/text_profile.rb +36 -0
- data/lib/omnizip/profile.rb +190 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +169 -0
- data/lib/omnizip/profiler.rb +204 -0
- data/lib/omnizip/progress/callback_reporter.rb +36 -0
- data/lib/omnizip/progress/console_reporter.rb +62 -0
- data/lib/omnizip/progress/log_reporter.rb +91 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +190 -0
- data/lib/omnizip/progress/silent_reporter.rb +24 -0
- data/lib/omnizip/progress.rb +127 -0
- data/lib/omnizip/rubyzip_compat.rb +63 -0
- data/lib/omnizip/temp/safe_extract.rb +168 -0
- data/lib/omnizip/temp/temp_file.rb +124 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +181 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +156 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +273 -0
- data/lib/omnizip/zip/output_stream.rb +324 -0
- data/lib/omnizip.rb +156 -0
- data/readme-docs/advanced-features.adoc +515 -0
- data/readme-docs/api-usage.adoc +444 -0
- data/readme-docs/architecture.adoc +449 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +442 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +325 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +617 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "galois16"
|
|
4
|
+
require_relative "par2cmdline_algorithm"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Parity
|
|
8
|
+
# Pure Reed-Solomon decoder for recovering missing blocks
|
|
9
|
+
# This is algorithm-only code with no I/O dependencies
|
|
10
|
+
#
|
|
11
|
+
# Recovers missing blocks by solving a system of linear equations
|
|
12
|
+
# using Gaussian elimination over GF(2^16)
|
|
13
|
+
class ReedSolomonDecoder
|
|
14
|
+
# Recover missing input blocks using available inputs and recovery blocks
|
|
15
|
+
#
|
|
16
|
+
# @param present_blocks [Hash<Integer, String>] Map of index => block data for present inputs
|
|
17
|
+
# @param recovery_blocks [Array<Hash>] Array of recovery block info: {data: String, exponent: Integer}
|
|
18
|
+
# @param missing_indices [Array<Integer>] Indices of missing input blocks to recover
|
|
19
|
+
# @param block_size [Integer] Size of each block in bytes
|
|
20
|
+
# @param total_inputs [Integer] Total number of input blocks (present + missing)
|
|
21
|
+
# @return [Hash<Integer, String>] Map of recovered index => block data
|
|
22
|
+
def self.decode(present_blocks, recovery_blocks, missing_indices,
|
|
23
|
+
block_size, total_inputs)
|
|
24
|
+
raise ArgumentError, "Block size must be even" if block_size.odd?
|
|
25
|
+
|
|
26
|
+
if missing_indices.empty?
|
|
27
|
+
raise ArgumentError,
|
|
28
|
+
"No missing blocks to recover"
|
|
29
|
+
end
|
|
30
|
+
if recovery_blocks.size < missing_indices.size
|
|
31
|
+
raise ArgumentError,
|
|
32
|
+
"Not enough recovery blocks"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Select base values using par2cmdline algorithm (same as encoder)
|
|
36
|
+
bases = Par2cmdlineAlgorithm.compute_bases(total_inputs)
|
|
37
|
+
|
|
38
|
+
# Build and solve the matrix system
|
|
39
|
+
solved_matrix = build_and_solve_matrix(
|
|
40
|
+
present_blocks.keys.sort,
|
|
41
|
+
missing_indices.sort,
|
|
42
|
+
recovery_blocks.map { |r| r[:exponent] },
|
|
43
|
+
bases,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Reconstruct missing blocks using solved matrix
|
|
47
|
+
reconstruct_missing_blocks(
|
|
48
|
+
present_blocks,
|
|
49
|
+
recovery_blocks,
|
|
50
|
+
missing_indices,
|
|
51
|
+
solved_matrix,
|
|
52
|
+
block_size,
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Build augmented matrix and solve using Gaussian elimination
|
|
57
|
+
#
|
|
58
|
+
# @param present_indices [Array<Integer>] Sorted indices of present blocks
|
|
59
|
+
# @param missing_indices [Array<Integer>] Sorted indices of missing blocks
|
|
60
|
+
# @param recovery_exponents [Array<Integer>] Exponents of recovery blocks
|
|
61
|
+
# @param bases [Array<Integer>] Base values for all inputs
|
|
62
|
+
# @return [Array<Array<Integer>>] Solved left matrix
|
|
63
|
+
def self.build_and_solve_matrix(present_indices, missing_indices,
|
|
64
|
+
recovery_exponents, bases)
|
|
65
|
+
num_present = present_indices.size
|
|
66
|
+
num_missing = missing_indices.size
|
|
67
|
+
recovery_exponents.size
|
|
68
|
+
|
|
69
|
+
# We use first num_missing recovery blocks to solve for missing data
|
|
70
|
+
num_rows = num_missing
|
|
71
|
+
num_cols = num_present + num_missing
|
|
72
|
+
|
|
73
|
+
# Allocate matrices
|
|
74
|
+
left_matrix = Array.new(num_rows) { Array.new(num_cols, 0) }
|
|
75
|
+
right_matrix = Array.new(num_rows) { Array.new(num_rows, 0) }
|
|
76
|
+
|
|
77
|
+
# Fill matrices using first num_missing recovery blocks
|
|
78
|
+
recovery_exponents.first(num_missing).each_with_index do |exponent, row|
|
|
79
|
+
# Left matrix: base^exponent for present inputs, identity for missing
|
|
80
|
+
present_indices.each_with_index do |idx, col|
|
|
81
|
+
left_matrix[row][col] = Galois16.power(bases[idx], exponent)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Identity block for missing data (helps in solving)
|
|
85
|
+
num_missing.times do |col|
|
|
86
|
+
left_matrix[row][num_present + col] = (row == col ? 1 : 0)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Right matrix: base^exponent for missing inputs
|
|
90
|
+
missing_indices.each_with_index do |idx, col|
|
|
91
|
+
right_matrix[row][col] = Galois16.power(bases[idx], exponent)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Solve using Gaussian elimination
|
|
96
|
+
gaussian_elimination(left_matrix, right_matrix)
|
|
97
|
+
|
|
98
|
+
left_matrix
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Perform Gaussian elimination to solve the matrix system
|
|
102
|
+
# Modifies matrices in place
|
|
103
|
+
#
|
|
104
|
+
# @param left_matrix [Array<Array<Integer>>] Left matrix (will be modified)
|
|
105
|
+
# @param right_matrix [Array<Array<Integer>>] Right matrix (will be modified)
|
|
106
|
+
def self.gaussian_elimination(left_matrix, right_matrix)
|
|
107
|
+
num_rows = left_matrix.size
|
|
108
|
+
num_left_cols = left_matrix[0].size
|
|
109
|
+
num_right_cols = right_matrix[0].size
|
|
110
|
+
|
|
111
|
+
# Forward elimination + back substitution
|
|
112
|
+
num_rows.times do |pivot_row|
|
|
113
|
+
# Get pivot value from right matrix diagonal
|
|
114
|
+
pivot = right_matrix[pivot_row][pivot_row]
|
|
115
|
+
raise "Singular matrix at row #{pivot_row}" if pivot.zero?
|
|
116
|
+
|
|
117
|
+
# Scale pivot row to make pivot = 1
|
|
118
|
+
unless pivot == 1
|
|
119
|
+
# Scale left matrix
|
|
120
|
+
num_left_cols.times do |col|
|
|
121
|
+
next if left_matrix[pivot_row][col].zero?
|
|
122
|
+
|
|
123
|
+
left_matrix[pivot_row][col] =
|
|
124
|
+
Galois16.divide(left_matrix[pivot_row][col], pivot)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Scale right matrix
|
|
128
|
+
right_matrix[pivot_row][pivot_row] = 1
|
|
129
|
+
((pivot_row + 1)...num_right_cols).each do |col|
|
|
130
|
+
next if right_matrix[pivot_row][col].zero?
|
|
131
|
+
|
|
132
|
+
right_matrix[pivot_row][col] =
|
|
133
|
+
Galois16.divide(right_matrix[pivot_row][col], pivot)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Eliminate column in all other rows
|
|
138
|
+
num_rows.times do |row|
|
|
139
|
+
next if row == pivot_row
|
|
140
|
+
|
|
141
|
+
scale = right_matrix[row][pivot_row]
|
|
142
|
+
next if scale.zero?
|
|
143
|
+
|
|
144
|
+
if scale == 1
|
|
145
|
+
# Optimization: just XOR subtract rows
|
|
146
|
+
num_left_cols.times do |col|
|
|
147
|
+
next if left_matrix[pivot_row][col].zero?
|
|
148
|
+
|
|
149
|
+
left_matrix[row][col] = Galois16.add(
|
|
150
|
+
left_matrix[row][col],
|
|
151
|
+
left_matrix[pivot_row][col],
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
(pivot_row...num_right_cols).each do |col|
|
|
156
|
+
next if right_matrix[pivot_row][col].zero?
|
|
157
|
+
|
|
158
|
+
right_matrix[row][col] = Galois16.add(
|
|
159
|
+
right_matrix[row][col],
|
|
160
|
+
right_matrix[pivot_row][col],
|
|
161
|
+
)
|
|
162
|
+
end
|
|
163
|
+
else
|
|
164
|
+
# General case: row -= pivot_row * scale
|
|
165
|
+
num_left_cols.times do |col|
|
|
166
|
+
next if left_matrix[pivot_row][col].zero?
|
|
167
|
+
|
|
168
|
+
scaled = Galois16.multiply(left_matrix[pivot_row][col], scale)
|
|
169
|
+
left_matrix[row][col] =
|
|
170
|
+
Galois16.add(left_matrix[row][col], scaled)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
(pivot_row...num_right_cols).each do |col|
|
|
174
|
+
next if right_matrix[pivot_row][col].zero?
|
|
175
|
+
|
|
176
|
+
scaled = Galois16.multiply(right_matrix[pivot_row][col], scale)
|
|
177
|
+
right_matrix[row][col] =
|
|
178
|
+
Galois16.add(right_matrix[row][col], scaled)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Reconstruct missing blocks using solved matrix
|
|
186
|
+
#
|
|
187
|
+
# @param present_blocks [Hash<Integer, String>] Present input blocks
|
|
188
|
+
# @param recovery_blocks [Array<Hash>] Recovery blocks with :data and :exponent
|
|
189
|
+
# @param missing_indices [Array<Integer>] Indices to recover
|
|
190
|
+
# @param solved_matrix [Array<Array<Integer>>] Solved coefficient matrix
|
|
191
|
+
# @param block_size [Integer] Block size in bytes
|
|
192
|
+
# @return [Hash<Integer, String>] Recovered blocks
|
|
193
|
+
def self.reconstruct_missing_blocks(present_blocks, recovery_blocks,
|
|
194
|
+
missing_indices, solved_matrix, block_size)
|
|
195
|
+
recovered = {}
|
|
196
|
+
|
|
197
|
+
missing_indices.each_with_index do |missing_idx, row|
|
|
198
|
+
# Initialize missing block to zeros
|
|
199
|
+
recovered_block = "\x00".b * block_size
|
|
200
|
+
|
|
201
|
+
# Add contribution from each present input block
|
|
202
|
+
present_blocks.each do |present_idx, present_data|
|
|
203
|
+
# Find column for this present block
|
|
204
|
+
col = present_blocks.keys.sort.index(present_idx)
|
|
205
|
+
factor = solved_matrix[row][col]
|
|
206
|
+
|
|
207
|
+
next if factor.zero?
|
|
208
|
+
|
|
209
|
+
# recovered_block ^= present_data * factor
|
|
210
|
+
process_block(factor, present_data, recovered_block, block_size)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Add contribution from each recovery block we're using
|
|
214
|
+
num_present = present_blocks.size
|
|
215
|
+
recovery_blocks.first(missing_indices.size).each_with_index do |recovery_info, rec_idx|
|
|
216
|
+
col = num_present + rec_idx
|
|
217
|
+
factor = solved_matrix[row][col]
|
|
218
|
+
|
|
219
|
+
next if factor.zero?
|
|
220
|
+
|
|
221
|
+
# recovered_block ^= recovery_data * factor
|
|
222
|
+
process_block(factor, recovery_info[:data], recovered_block,
|
|
223
|
+
block_size)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
recovered[missing_idx] = recovered_block
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
recovered
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Core operation: output_block ^= input_block * factor (in GF(2^16))
|
|
233
|
+
# Same as encoder's process_block
|
|
234
|
+
#
|
|
235
|
+
# @param factor [Integer] Galois field multiplier
|
|
236
|
+
# @param input_block [String] Input data
|
|
237
|
+
# @param output_block [String] Output data (modified in place)
|
|
238
|
+
# @param block_size [Integer] Block size in bytes
|
|
239
|
+
def self.process_block(factor, input_block, output_block, block_size)
|
|
240
|
+
num_words = block_size / 2
|
|
241
|
+
|
|
242
|
+
num_words.times do |i|
|
|
243
|
+
offset = i * 2
|
|
244
|
+
|
|
245
|
+
# Read 16-bit words (little-endian)
|
|
246
|
+
input_word = input_block.getbyte(offset) |
|
|
247
|
+
(input_block.getbyte(offset + 1) << 8)
|
|
248
|
+
|
|
249
|
+
output_word = output_block.getbyte(offset) |
|
|
250
|
+
(output_block.getbyte(offset + 1) << 8)
|
|
251
|
+
|
|
252
|
+
# Galois multiplication and addition (XOR)
|
|
253
|
+
result = Galois16.add(output_word,
|
|
254
|
+
Galois16.multiply(input_word, factor))
|
|
255
|
+
|
|
256
|
+
# Write back as bytes (little-endian)
|
|
257
|
+
output_block.setbyte(offset, result & 0xFF)
|
|
258
|
+
output_block.setbyte(offset + 1, (result >> 8) & 0xFF)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
private_class_method :build_and_solve_matrix, :gaussian_elimination,
|
|
263
|
+
:reconstruct_missing_blocks, :process_block
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "galois16"
|
|
4
|
+
require_relative "par2cmdline_algorithm"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Parity
|
|
8
|
+
# Pure Reed-Solomon encoder for creating recovery blocks
|
|
9
|
+
# This is algorithm-only code with no I/O dependencies
|
|
10
|
+
#
|
|
11
|
+
# Creates recovery blocks using Vandermonde matrix over GF(2^16):
|
|
12
|
+
# Recovery[i] = sum(Input[j] * Base[j]^Exponent[i] for all j)
|
|
13
|
+
class ReedSolomonEncoder
|
|
14
|
+
# Create recovery blocks from input blocks
|
|
15
|
+
#
|
|
16
|
+
# @param input_blocks [Array<String>] Array of input block data (binary strings)
|
|
17
|
+
# @param block_size [Integer] Size of each block in bytes (must be even for 16-bit processing)
|
|
18
|
+
# @param exponents [Array<Integer>] Exponent for each recovery block (0-65535)
|
|
19
|
+
# @return [Array<String>] Array of recovery block data (binary strings)
|
|
20
|
+
def self.encode(input_blocks, block_size, exponents)
|
|
21
|
+
if block_size.odd?
|
|
22
|
+
raise ArgumentError,
|
|
23
|
+
"Block size must be even for 16-bit processing"
|
|
24
|
+
end
|
|
25
|
+
raise ArgumentError, "No input blocks provided" if input_blocks.empty?
|
|
26
|
+
raise ArgumentError, "No exponents provided" if exponents.empty?
|
|
27
|
+
|
|
28
|
+
# Validate all input blocks have correct size
|
|
29
|
+
input_blocks.each_with_index do |block, idx|
|
|
30
|
+
unless block.bytesize == block_size
|
|
31
|
+
raise ArgumentError,
|
|
32
|
+
"Input block #{idx} has size #{block.bytesize}, expected #{block_size}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Select base values using par2cmdline algorithm
|
|
37
|
+
num_inputs = input_blocks.length
|
|
38
|
+
bases = Par2cmdlineAlgorithm.compute_bases(num_inputs)
|
|
39
|
+
|
|
40
|
+
# Create recovery blocks
|
|
41
|
+
recovery_blocks = []
|
|
42
|
+
exponents.each do |exponent|
|
|
43
|
+
recovery_block = create_recovery_block(input_blocks, bases, exponent,
|
|
44
|
+
block_size)
|
|
45
|
+
recovery_blocks << recovery_block
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
recovery_blocks
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Create a single recovery block
|
|
52
|
+
#
|
|
53
|
+
# @param input_blocks [Array<String>] Input block data
|
|
54
|
+
# @param bases [Array<Integer>] Base values for each input
|
|
55
|
+
# @param exponent [Integer] Exponent for this recovery block
|
|
56
|
+
# @param block_size [Integer] Block size in bytes
|
|
57
|
+
# @return [String] Recovery block data
|
|
58
|
+
def self.create_recovery_block(input_blocks, bases, exponent, block_size)
|
|
59
|
+
# Initialize recovery block to zeros
|
|
60
|
+
recovery_data = "\x00".b * block_size
|
|
61
|
+
|
|
62
|
+
# Process each input block
|
|
63
|
+
input_blocks.each_with_index do |input_block, idx|
|
|
64
|
+
# Compute factor = base[idx]^exponent
|
|
65
|
+
factor = Galois16.power(bases[idx], exponent)
|
|
66
|
+
|
|
67
|
+
# Skip if factor is zero (optimization)
|
|
68
|
+
next if factor.zero?
|
|
69
|
+
|
|
70
|
+
# Add input_block * factor to recovery_block
|
|
71
|
+
process_block(factor, input_block, recovery_data, block_size)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
recovery_data
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Core operation: output_block ^= input_block * factor (in GF(2^16))
|
|
78
|
+
# Processes data as 16-bit words in little-endian format
|
|
79
|
+
#
|
|
80
|
+
# @param factor [Integer] Galois field multiplier
|
|
81
|
+
# @param input_block [String] Input data
|
|
82
|
+
# @param output_block [String] Output data (modified in place)
|
|
83
|
+
# @param block_size [Integer] Block size in bytes
|
|
84
|
+
def self.process_block(factor, input_block, output_block, block_size)
|
|
85
|
+
# Process as 16-bit words (little-endian)
|
|
86
|
+
num_words = block_size / 2
|
|
87
|
+
|
|
88
|
+
num_words.times do |i|
|
|
89
|
+
offset = i * 2
|
|
90
|
+
|
|
91
|
+
# Read 16-bit words (little-endian)
|
|
92
|
+
input_word = input_block.getbyte(offset) |
|
|
93
|
+
(input_block.getbyte(offset + 1) << 8)
|
|
94
|
+
|
|
95
|
+
output_word = output_block.getbyte(offset) |
|
|
96
|
+
(output_block.getbyte(offset + 1) << 8)
|
|
97
|
+
|
|
98
|
+
# Galois multiplication and addition (XOR)
|
|
99
|
+
result = Galois16.add(output_word,
|
|
100
|
+
Galois16.multiply(input_word, factor))
|
|
101
|
+
|
|
102
|
+
# Write back as bytes (little-endian)
|
|
103
|
+
output_block.setbyte(offset, result & 0xFF)
|
|
104
|
+
output_block.setbyte(offset + 1, (result >> 8) & 0xFF)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private_class_method :create_recovery_block, :process_block
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|