omnizip 0.4.7-x86_64-linux
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 +293 -0
- data/CHANGELOG.md +1647 -0
- data/CONTEXT.md +68 -0
- data/COPYING +502 -0
- data/Gemfile +19 -0
- data/LICENSE +12 -0
- data/README.adoc +1327 -0
- data/Rakefile +15 -0
- data/TODO.refactor/00-overview.md +67 -0
- data/TODO.refactor/01-registry-base-class.md +81 -0
- data/TODO.refactor/02-error-hierarchy.md +57 -0
- data/TODO.refactor/03-autoload-entry-point.md +69 -0
- data/TODO.refactor/04-filter-base-consolidation.md +49 -0
- data/TODO.refactor/05-send-private-methods.md +64 -0
- data/TODO.refactor/06-instance-variable-access.md +69 -0
- data/TODO.refactor/07-respond-to-replacement.md +237 -0
- data/TODO.refactor/08-spec-doubles.md +27 -0
- data/TODO.refactor/09-cli-shared-module.md +35 -0
- data/TODO.refactor/10-format-detector-ocp.md +34 -0
- data/TODO.refactor/11-convenience-decoupling.md +38 -0
- data/TODO.refactor/12-thread-safety.md +8 -0
- data/TODO.refactor/13-lutaml-model-migration.md +158 -0
- data/TODO.refactor/14-add-missing-specs.md +25 -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 +92 -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 +263 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +183 -0
- data/docs/getting-started/your-first-archive.adoc +219 -0
- data/docs/guides/advanced-features/encryption.adoc +277 -0
- data/docs/guides/advanced-features/index.adoc +59 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
- data/docs/guides/advanced-features/streaming.adoc +142 -0
- data/docs/guides/archive-formats/gzip-format.adoc +105 -0
- data/docs/guides/archive-formats/index.adoc +160 -0
- data/docs/guides/archive-formats/ole-format.adoc +151 -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/rpm-format.adoc +108 -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 +114 -0
- data/docs/guides/compression-algorithms/deflate.adoc +313 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +394 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
- data/docs/guides/creating-archives.adoc +348 -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 +228 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +187 -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/rust-backend.md +0 -0
- data/docs/troubleshooting/index.adoc +207 -0
- data/docs/xar_format.md +216 -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 +176 -0
- data/lib/omnizip/algorithm_registry.rb +65 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
- data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
- data/lib/omnizip/algorithms/bzip2.rb +108 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
- data/lib/omnizip/algorithms/deflate.rb +135 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
- data/lib/omnizip/algorithms/deflate64.rb +118 -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 +146 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
- data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -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 +233 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
- data/lib/omnizip/algorithms/lzma.rb +266 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +133 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +146 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +122 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
- data/lib/omnizip/algorithms/registration.rb +28 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
- data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
- data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
- data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
- data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
- data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +210 -0
- data/lib/omnizip/algorithms.rb +35 -0
- data/lib/omnizip/archive/builder.rb +48 -0
- data/lib/omnizip/archive/reader_session.rb +67 -0
- data/lib/omnizip/archive.rb +86 -0
- data/lib/omnizip/archive_handler.rb +82 -0
- data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
- data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
- data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
- data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
- data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
- data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
- data/lib/omnizip/archive_handlers.rb +18 -0
- data/lib/omnizip/backends.rb +160 -0
- data/lib/omnizip/buffer/memory_archive.rb +246 -0
- data/lib/omnizip/buffer/memory_extractor.rb +234 -0
- data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
- data/lib/omnizip/buffer.rb +187 -0
- data/lib/omnizip/checksum_registry.rb +41 -0
- data/lib/omnizip/checksums/crc32.rb +101 -0
- data/lib/omnizip/checksums/crc64.rb +102 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/registration.rb +16 -0
- data/lib/omnizip/checksums/verifier.rb +130 -0
- data/lib/omnizip/checksums.rb +11 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +123 -0
- data/lib/omnizip/chunked.rb +123 -0
- data/lib/omnizip/cli/output_formatter.rb +112 -0
- data/lib/omnizip/cli.rb +604 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +245 -0
- data/lib/omnizip/commands/archive_extract_command.rb +231 -0
- data/lib/omnizip/commands/archive_list_command.rb +204 -0
- data/lib/omnizip/commands/archive_repair_command.rb +129 -0
- data/lib/omnizip/commands/archive_verify_command.rb +115 -0
- data/lib/omnizip/commands/compress_command.rb +115 -0
- data/lib/omnizip/commands/decompress_command.rb +149 -0
- data/lib/omnizip/commands/list_command.rb +51 -0
- data/lib/omnizip/commands/metadata_command.rb +215 -0
- data/lib/omnizip/commands/parity_create_command.rb +114 -0
- data/lib/omnizip/commands/parity_repair_command.rb +120 -0
- data/lib/omnizip/commands/parity_verify_command.rb +122 -0
- data/lib/omnizip/commands/profile_list_command.rb +54 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/commands.rb +21 -0
- data/lib/omnizip/convenience.rb +389 -0
- data/lib/omnizip/converter/conversion_registry.rb +50 -0
- data/lib/omnizip/converter/conversion_strategy.rb +108 -0
- data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
- data/lib/omnizip/converter.rb +124 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/crypto.rb +11 -0
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/error.rb +110 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +96 -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 +68 -0
- data/lib/omnizip/extraction/filter_chain.rb +179 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +66 -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 +247 -0
- data/lib/omnizip/extraction.rb +115 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +117 -0
- data/lib/omnizip/filter.rb +141 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +113 -0
- data/lib/omnizip/filters/bcj.rb +277 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
- data/lib/omnizip/filters/bcj2.rb +93 -0
- data/lib/omnizip/filters/bcj_arm.rb +174 -0
- data/lib/omnizip/filters/bcj_arm64.rb +242 -0
- data/lib/omnizip/filters/bcj_ia64.rb +194 -0
- data/lib/omnizip/filters/bcj_ppc.rb +188 -0
- data/lib/omnizip/filters/bcj_sparc.rb +174 -0
- data/lib/omnizip/filters/bcj_x86.rb +191 -0
- data/lib/omnizip/filters/delta.rb +195 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/filters.rb +20 -0
- data/lib/omnizip/format_detector.rb +166 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +159 -0
- data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +389 -0
- data/lib/omnizip/formats/cpio/reader.rb +194 -0
- data/lib/omnizip/formats/cpio/writer.rb +232 -0
- data/lib/omnizip/formats/cpio.rb +132 -0
- data/lib/omnizip/formats/format_spec_loader.rb +228 -0
- data/lib/omnizip/formats/gzip.rb +236 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
- data/lib/omnizip/formats/iso/directory_record.rb +162 -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 +194 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +543 -0
- data/lib/omnizip/formats/iso.rb +133 -0
- data/lib/omnizip/formats/lzip.rb +161 -0
- data/lib/omnizip/formats/lzma_alone.rb +149 -0
- data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
- data/lib/omnizip/formats/msi/constants.rb +157 -0
- data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
- data/lib/omnizip/formats/msi/entry.rb +134 -0
- data/lib/omnizip/formats/msi/reader.rb +301 -0
- data/lib/omnizip/formats/msi/string_pool.rb +246 -0
- data/lib/omnizip/formats/msi/table_parser.rb +244 -0
- data/lib/omnizip/formats/msi.rb +73 -0
- data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
- data/lib/omnizip/formats/ole/constants.rb +61 -0
- data/lib/omnizip/formats/ole/dirent.rb +439 -0
- data/lib/omnizip/formats/ole/header.rb +199 -0
- data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
- data/lib/omnizip/formats/ole/storage.rb +482 -0
- data/lib/omnizip/formats/ole/types/variant.rb +338 -0
- data/lib/omnizip/formats/ole.rb +143 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
- data/lib/omnizip/formats/rar/block_parser.rb +282 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -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/lz77_huffman.rb +25 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
- data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
- data/lib/omnizip/formats/rar/compression.rb +17 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +88 -0
- data/lib/omnizip/formats/rar/decompressor.rb +316 -0
- data/lib/omnizip/formats/rar/external_writer.rb +311 -0
- data/lib/omnizip/formats/rar/header.rb +209 -0
- data/lib/omnizip/formats/rar/license_validator.rb +111 -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/models.rb +14 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -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 +96 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +208 -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 +260 -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 +176 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
- data/lib/omnizip/formats/rar/reader.rb +377 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
- data/lib/omnizip/formats/rar/writer.rb +437 -0
- data/lib/omnizip/formats/rar.rb +193 -0
- data/lib/omnizip/formats/rar3/compressor.rb +71 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar3/reader.rb +107 -0
- data/lib/omnizip/formats/rar3/writer.rb +220 -0
- data/lib/omnizip/formats/rar3.rb +15 -0
- data/lib/omnizip/formats/rar5/compressor.rb +71 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar5/reader.rb +130 -0
- data/lib/omnizip/formats/rar5/writer.rb +65 -0
- data/lib/omnizip/formats/rar5.rb +15 -0
- data/lib/omnizip/formats/rpm/constants.rb +58 -0
- data/lib/omnizip/formats/rpm/entry.rb +106 -0
- data/lib/omnizip/formats/rpm/header.rb +106 -0
- data/lib/omnizip/formats/rpm/lead.rb +132 -0
- data/lib/omnizip/formats/rpm/tag.rb +228 -0
- data/lib/omnizip/formats/rpm/writer.rb +652 -0
- data/lib/omnizip/formats/rpm.rb +458 -0
- data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
- data/lib/omnizip/formats/seven_zip/header.rb +102 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/models.rb +20 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
- data/lib/omnizip/formats/seven_zip.rb +179 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +98 -0
- data/lib/omnizip/formats/tar/header.rb +206 -0
- data/lib/omnizip/formats/tar/reader.rb +119 -0
- data/lib/omnizip/formats/tar/writer.rb +212 -0
- data/lib/omnizip/formats/tar.rb +74 -0
- data/lib/omnizip/formats/xar/constants.rb +119 -0
- data/lib/omnizip/formats/xar/entry.rb +268 -0
- data/lib/omnizip/formats/xar/header.rb +223 -0
- data/lib/omnizip/formats/xar/reader.rb +400 -0
- data/lib/omnizip/formats/xar/toc.rb +570 -0
- data/lib/omnizip/formats/xar/writer.rb +461 -0
- data/lib/omnizip/formats/xar.rb +145 -0
- data/lib/omnizip/formats/xz/reader.rb +121 -0
- data/lib/omnizip/formats/xz/writer.rb +416 -0
- data/lib/omnizip/formats/xz.rb +210 -0
- data/lib/omnizip/formats/xz_const.rb +49 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl.rb +52 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
- data/lib/omnizip/formats/zip/reader.rb +376 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +489 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/formats.rb +29 -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/base.rb +19 -0
- data/lib/omnizip/implementations/rust/archive.rb +93 -0
- data/lib/omnizip/implementations/rust/library.rb +221 -0
- data/lib/omnizip/implementations/rust.rb +26 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
- data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
- data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
- data/lib/omnizip/implementations/seven_zip.rb +11 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
- data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
- data/lib/omnizip/implementations/xz_utils.rb +10 -0
- data/lib/omnizip/implementations.rb +25 -0
- data/lib/omnizip/io/buffered_input.rb +147 -0
- data/lib/omnizip/io/buffered_output.rb +106 -0
- data/lib/omnizip/io/source.rb +143 -0
- data/lib/omnizip/io/stream_manager.rb +117 -0
- data/lib/omnizip/io.rb +15 -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 +129 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +153 -0
- data/lib/omnizip/metadata/metadata_editor.rb +169 -0
- data/lib/omnizip/metadata/metadata_registry.rb +71 -0
- data/lib/omnizip/metadata/metadata_validator.rb +101 -0
- data/lib/omnizip/metadata.rb +58 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +41 -0
- data/lib/omnizip/models/attribute_apply.rb +40 -0
- data/lib/omnizip/models/compression_options.rb +53 -0
- data/lib/omnizip/models/conversion_options.rb +79 -0
- data/lib/omnizip/models/conversion_result.rb +141 -0
- data/lib/omnizip/models/eta_result.rb +45 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +142 -0
- data/lib/omnizip/models/filter_config.rb +148 -0
- data/lib/omnizip/models/match_result.rb +141 -0
- data/lib/omnizip/models/optimization_suggestion.rb +95 -0
- data/lib/omnizip/models/parallel_options.rb +116 -0
- data/lib/omnizip/models/performance_result.rb +85 -0
- data/lib/omnizip/models/profile_report.rb +116 -0
- data/lib/omnizip/models/progress_options.rb +39 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +45 -0
- data/lib/omnizip/parallel/engine.rb +52 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +225 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
- data/lib/omnizip/parallel/thread_pool.rb +60 -0
- data/lib/omnizip/parallel/worker_pool.rb +227 -0
- data/lib/omnizip/parallel.rb +156 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +71 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
- data/lib/omnizip/parity/models/main_packet.rb +126 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +102 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
- data/lib/omnizip/parity/models.rb +27 -0
- data/lib/omnizip/parity/par2_creator.rb +496 -0
- data/lib/omnizip/parity/par2_repairer.rb +409 -0
- data/lib/omnizip/parity/par2_verifier.rb +373 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
- data/lib/omnizip/parity.rb +207 -0
- data/lib/omnizip/password/encryption_registry.rb +26 -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 +190 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
- data/lib/omnizip/password.rb +88 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
- data/lib/omnizip/pipe.rb +120 -0
- data/lib/omnizip/platform/ntfs_streams.rb +200 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +36 -0
- data/lib/omnizip/profile/balanced_profile.rb +31 -0
- data/lib/omnizip/profile/binary_profile.rb +33 -0
- data/lib/omnizip/profile/compression_profile.rb +157 -0
- data/lib/omnizip/profile/custom_profile.rb +155 -0
- data/lib/omnizip/profile/fast_profile.rb +31 -0
- data/lib/omnizip/profile/maximum_profile.rb +31 -0
- data/lib/omnizip/profile/profile_detector.rb +108 -0
- data/lib/omnizip/profile/profile_registry.rb +160 -0
- data/lib/omnizip/profile/text_profile.rb +33 -0
- data/lib/omnizip/profile.rb +261 -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 +158 -0
- data/lib/omnizip/profiler.rb +192 -0
- data/lib/omnizip/progress/callback_reporter.rb +34 -0
- data/lib/omnizip/progress/console_reporter.rb +59 -0
- data/lib/omnizip/progress/log_reporter.rb +89 -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 +215 -0
- data/lib/omnizip/progress/silent_reporter.rb +22 -0
- data/lib/omnizip/progress.rb +131 -0
- data/lib/omnizip/registry.rb +111 -0
- data/lib/omnizip/rubyzip_compat.rb +61 -0
- data/lib/omnizip/temp/safe_extract.rb +124 -0
- data/lib/omnizip/temp/temp_file.rb +123 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +184 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +160 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +270 -0
- data/lib/omnizip/zip/output_stream.rb +320 -0
- data/lib/omnizip/zip.rb +23 -0
- data/lib/omnizip.rb +157 -0
- data/lib/tasks/msi_test_files.rake +66 -0
- data/lib/tasks/platform_gems.rake +147 -0
- data/lib/tasks/rust_backend.rake +48 -0
- data/readme-docs/advanced-features.adoc +514 -0
- data/readme-docs/api-usage.adoc +445 -0
- data/readme-docs/architecture.adoc +450 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +446 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +316 -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/vendor/libomnizip_ffi.so +0 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +768 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
7
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
8
|
+
# to deal in the Software without restriction, including without limitation
|
|
9
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
10
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
11
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
|
14
|
+
# all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
22
|
+
# DEALINGS IN THE SOFTWARE.
|
|
23
|
+
#
|
|
24
|
+
# XZ Utils Delta filter implementation.
|
|
25
|
+
#
|
|
26
|
+
# This is the XZ Utils Delta filter (filter ID 0x03), which is DIFFERENT
|
|
27
|
+
# from the 7-Zip Delta filter. Both compute byte-wise differences but use
|
|
28
|
+
# different algorithms:
|
|
29
|
+
#
|
|
30
|
+
# - 7-Zip Delta: Simple forward difference (new[i] = old[i] - old[i-distance])
|
|
31
|
+
# - XZ Utils Delta: Uses a 256-byte circular history buffer
|
|
32
|
+
#
|
|
33
|
+
# Reference: /Users/mulgogi/src/external/xz/src/liblzma/delta/
|
|
34
|
+
#
|
|
35
|
+
# Algorithm summary:
|
|
36
|
+
# - Maintains a 256-byte circular history buffer
|
|
37
|
+
# - Encoder: out[i] = in[i] - history[(distance + pos) & 0xFF]
|
|
38
|
+
# - Decoder: out[i] = in[i] + history[(distance + pos) & 0xFF]
|
|
39
|
+
# - history[pos & 0xFF] = processed_byte (updated in both encode/decode)
|
|
40
|
+
# - pos decrements each byte, wrapping via & 0xFF
|
|
41
|
+
#
|
|
42
|
+
# The distance parameter (1-256) determines how far back in the history
|
|
43
|
+
# to look for the delta reference value.
|
|
44
|
+
|
|
45
|
+
module Omnizip
|
|
46
|
+
module Filters
|
|
47
|
+
# XZ Utils Delta filter.
|
|
48
|
+
#
|
|
49
|
+
# This filter computes byte-wise differences using a 256-byte circular
|
|
50
|
+
# history buffer. It is particularly effective for:
|
|
51
|
+
# - Stereo audio (distance=4 for 16-bit samples)
|
|
52
|
+
# - RGB images (distance=3)
|
|
53
|
+
# - RGBA images (distance=4)
|
|
54
|
+
# - Multi-channel data with regular patterns
|
|
55
|
+
#
|
|
56
|
+
# This is DIFFERENT from the 7-Zip Delta filter which uses simple
|
|
57
|
+
# forward differences without a history buffer.
|
|
58
|
+
#
|
|
59
|
+
# Reference: XZ Utils delta_encoder.c, delta_decoder.c
|
|
60
|
+
class XzDeltaFilter
|
|
61
|
+
# Filter ID for XZ format
|
|
62
|
+
FILTER_ID = 0x03
|
|
63
|
+
|
|
64
|
+
# Minimum distance value (XZ Utils LZMA_DELTA_DIST_MIN)
|
|
65
|
+
DELTA_DIST_MIN = 1
|
|
66
|
+
|
|
67
|
+
# Maximum distance value (XZ Utils LZMA_DELTA_DIST_MAX)
|
|
68
|
+
DELTA_DIST_MAX = 256
|
|
69
|
+
|
|
70
|
+
# History buffer size (always 256 bytes in XZ Utils)
|
|
71
|
+
HISTORY_SIZE = 256
|
|
72
|
+
|
|
73
|
+
# Delta type (only BYTE is supported in XZ Utils)
|
|
74
|
+
DELTA_TYPE_BYTE = 0
|
|
75
|
+
|
|
76
|
+
attr_reader :distance
|
|
77
|
+
|
|
78
|
+
# Initialize the Delta filter.
|
|
79
|
+
#
|
|
80
|
+
# @param distance [Integer] Byte distance for delta calculation (1-256)
|
|
81
|
+
# @raise [ArgumentError] If distance is invalid
|
|
82
|
+
def initialize(distance = DELTA_DIST_MIN)
|
|
83
|
+
validate_distance(distance)
|
|
84
|
+
@distance = distance
|
|
85
|
+
# Initialize state (matches XZ Utils lzma_delta_coder_init)
|
|
86
|
+
@pos = 0
|
|
87
|
+
@history = ("\x00" * HISTORY_SIZE).b
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Encode (preprocess) data by computing forward differences.
|
|
91
|
+
#
|
|
92
|
+
# For each byte:
|
|
93
|
+
# tmp = history[(distance + pos) & 0xFF]
|
|
94
|
+
# history[pos & 0xFF] = in[i]
|
|
95
|
+
# out[i] = in[i] - tmp (mod 256)
|
|
96
|
+
# pos--
|
|
97
|
+
#
|
|
98
|
+
# Reference: XZ Utils delta_encoder.c:copy_and_encode
|
|
99
|
+
#
|
|
100
|
+
# @param data [String] Binary data to encode
|
|
101
|
+
# @return [String] Encoded binary data
|
|
102
|
+
def encode(data)
|
|
103
|
+
return data.dup.b if data.empty?
|
|
104
|
+
|
|
105
|
+
result = data.dup.b
|
|
106
|
+
data.bytes.each_with_index do |byte, i|
|
|
107
|
+
# Get historical value from distance positions back
|
|
108
|
+
tmp = @history.getbyte((@distance + @pos) & 0xFF)
|
|
109
|
+
|
|
110
|
+
# Store current byte in history
|
|
111
|
+
@history.setbyte(@pos & 0xFF, byte)
|
|
112
|
+
|
|
113
|
+
# Output is the difference
|
|
114
|
+
result.setbyte(i, (byte - tmp) & 0xFF)
|
|
115
|
+
|
|
116
|
+
# Move position backward (wraps via & 0xFF)
|
|
117
|
+
@pos = (@pos - 1) & 0xFF
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
result
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Decode (postprocess) data by restoring from differences.
|
|
124
|
+
#
|
|
125
|
+
# For each byte:
|
|
126
|
+
# buffer[i] += history[(distance + pos) & 0xFF] (mod 256)
|
|
127
|
+
# history[pos & 0xFF] = buffer[i]
|
|
128
|
+
# pos--
|
|
129
|
+
#
|
|
130
|
+
# Reference: XZ Utils delta_decoder.c:decode_buffer
|
|
131
|
+
#
|
|
132
|
+
# @param data [String] Binary data to decode
|
|
133
|
+
# @return [String] Decoded binary data
|
|
134
|
+
def decode(data)
|
|
135
|
+
return data.dup.b if data.empty?
|
|
136
|
+
|
|
137
|
+
result = data.dup.b
|
|
138
|
+
data.bytes.each_with_index do |byte, i|
|
|
139
|
+
# Get historical value from distance positions back
|
|
140
|
+
tmp = @history.getbyte((@distance + @pos) & 0xFF)
|
|
141
|
+
|
|
142
|
+
# Restore original value by adding the difference
|
|
143
|
+
result.setbyte(i, (byte + tmp) & 0xFF)
|
|
144
|
+
|
|
145
|
+
# Store restored byte in history
|
|
146
|
+
@history.setbyte(@pos & 0xFF, result.getbyte(i))
|
|
147
|
+
|
|
148
|
+
# Move position backward (wraps via & 0xFF)
|
|
149
|
+
@pos = (@pos - 1) & 0xFF
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
result
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Reset the filter state.
|
|
156
|
+
#
|
|
157
|
+
# This clears the history buffer and resets position to 0.
|
|
158
|
+
# Used when initializing a new filter chain.
|
|
159
|
+
#
|
|
160
|
+
# @return [void]
|
|
161
|
+
def reset
|
|
162
|
+
@pos = 0
|
|
163
|
+
@history = ("\x00" * HISTORY_SIZE).b
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
class << self
|
|
167
|
+
# Decode properties byte to get distance.
|
|
168
|
+
#
|
|
169
|
+
# XZ Utils encodes distance as: props[0] = dist - 1
|
|
170
|
+
# So we decode as: dist = props[0] + 1
|
|
171
|
+
#
|
|
172
|
+
# Reference: XZ Utils delta_decoder.c:lzma_delta_props_decode
|
|
173
|
+
#
|
|
174
|
+
# @param properties [String] Properties byte (1 byte)
|
|
175
|
+
# @return [Integer] Distance value (1-256)
|
|
176
|
+
# @raise [ArgumentError] If properties size is invalid
|
|
177
|
+
def decode_properties(properties)
|
|
178
|
+
unless properties.is_a?(String) && properties.bytesize == 1
|
|
179
|
+
raise ArgumentError,
|
|
180
|
+
"Delta filter requires exactly 1 property byte, got #{properties&.bytesize}"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
props_byte = properties.getbyte(0)
|
|
184
|
+
# XZ Utils: opt->dist = props[0] + LZMA_DELTA_DIST_MIN
|
|
185
|
+
# where LZMA_DELTA_DIST_MIN = 1
|
|
186
|
+
distance = props_byte + DELTA_DIST_MIN
|
|
187
|
+
|
|
188
|
+
# Validate distance is in valid range (inline for class method)
|
|
189
|
+
unless distance.between?(DELTA_DIST_MIN, DELTA_DIST_MAX)
|
|
190
|
+
raise ArgumentError,
|
|
191
|
+
"Invalid distance #{distance}, must be between #{DELTA_DIST_MIN} and #{DELTA_DIST_MAX}"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
distance
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Encode distance to properties byte.
|
|
198
|
+
#
|
|
199
|
+
# XZ Utils encodes distance as: props[0] = dist - 1
|
|
200
|
+
#
|
|
201
|
+
# Reference: XZ Utils delta_encoder.c:lzma_delta_props_encode
|
|
202
|
+
#
|
|
203
|
+
# @param distance [Integer] Distance value (1-256)
|
|
204
|
+
# @return [String] Properties byte (1 byte)
|
|
205
|
+
# @raise [ArgumentError] If distance is invalid
|
|
206
|
+
def encode_properties(distance)
|
|
207
|
+
# Validate distance (inline for class method)
|
|
208
|
+
unless distance.is_a?(Integer)
|
|
209
|
+
raise ArgumentError,
|
|
210
|
+
"Distance must be an integer, got #{distance.class}"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
unless distance.between?(DELTA_DIST_MIN, DELTA_DIST_MAX)
|
|
214
|
+
raise ArgumentError,
|
|
215
|
+
"Distance must be between #{DELTA_DIST_MIN} and #{DELTA_DIST_MAX}, got #{distance}"
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# XZ Utils: out[0] = opt->dist - LZMA_DELTA_DIST_MIN
|
|
219
|
+
# where LZMA_DELTA_DIST_MIN = 1
|
|
220
|
+
props_byte = distance - DELTA_DIST_MIN
|
|
221
|
+
|
|
222
|
+
[props_byte].pack("C")
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Get metadata about this filter.
|
|
226
|
+
#
|
|
227
|
+
# @return [Hash] Filter metadata
|
|
228
|
+
def metadata
|
|
229
|
+
{
|
|
230
|
+
name: "XZ Delta",
|
|
231
|
+
description: "XZ Utils Delta filter with 256-byte circular history buffer",
|
|
232
|
+
filter_id: FILTER_ID,
|
|
233
|
+
typical_usage: "WAV audio (distance=4), BMP images (distance=3), " \
|
|
234
|
+
"multi-channel data with regular patterns",
|
|
235
|
+
}
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
private
|
|
240
|
+
|
|
241
|
+
# Validate distance parameter.
|
|
242
|
+
#
|
|
243
|
+
# @param dist [Integer] Distance value to validate
|
|
244
|
+
# @raise [ArgumentError] If distance is invalid
|
|
245
|
+
# @return [void]
|
|
246
|
+
def validate_distance(dist)
|
|
247
|
+
unless dist.is_a?(Integer)
|
|
248
|
+
raise ArgumentError, "Distance must be an integer, got #{dist.class}"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
unless dist.between?(DELTA_DIST_MIN, DELTA_DIST_MAX)
|
|
252
|
+
raise ArgumentError,
|
|
253
|
+
"Distance must be between #{DELTA_DIST_MIN} and #{DELTA_DIST_MAX}, got #{dist}"
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
# Filter implementations for preprocessing data before compression
|
|
5
|
+
module Filters
|
|
6
|
+
autoload :BCJ, "omnizip/filters/bcj"
|
|
7
|
+
autoload :BcjX86, "omnizip/filters/bcj_x86"
|
|
8
|
+
autoload :Bcj2, "omnizip/filters/bcj2"
|
|
9
|
+
autoload :Bcj2Constants, "omnizip/filters/bcj2/constants"
|
|
10
|
+
autoload :Bcj2StreamData, "omnizip/filters/bcj2/stream_data"
|
|
11
|
+
autoload :Bcj2Decoder, "omnizip/filters/bcj2/decoder"
|
|
12
|
+
autoload :Bcj2Encoder, "omnizip/filters/bcj2/encoder"
|
|
13
|
+
autoload :BcjArm, "omnizip/filters/bcj_arm"
|
|
14
|
+
autoload :BcjArm64, "omnizip/filters/bcj_arm64"
|
|
15
|
+
autoload :BcjPpc, "omnizip/filters/bcj_ppc"
|
|
16
|
+
autoload :BcjSparc, "omnizip/filters/bcj_sparc"
|
|
17
|
+
autoload :BcjIa64, "omnizip/filters/bcj_ia64"
|
|
18
|
+
autoload :Delta, "omnizip/filters/delta"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
# Detects archive format from file signature/magic bytes
|
|
5
|
+
#
|
|
6
|
+
# This class identifies archive formats based on their file signatures.
|
|
7
|
+
# It distinguishes between XZ Utils format (.xz) and 7-Zip format (.7z)
|
|
8
|
+
# which are DIFFERENT implementations of LZMA/LZMA2 compression.
|
|
9
|
+
#
|
|
10
|
+
# @example Basic usage
|
|
11
|
+
# format = Omnizip::FormatDetector.detect("archive.xz")
|
|
12
|
+
# case format
|
|
13
|
+
# when :xz
|
|
14
|
+
# # Use XZ Utils implementation
|
|
15
|
+
# when :seven_zip
|
|
16
|
+
# # Use 7-Zip implementation
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
class FormatDetector
|
|
20
|
+
# XZ Utils format signature: "\xFD7zXZ\x00"
|
|
21
|
+
XZ_SIGNATURE = [0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00].freeze
|
|
22
|
+
|
|
23
|
+
# 7-Zip format signature: "7z\xBC\xAF\x27\x1C"
|
|
24
|
+
SEVEN_ZIP_SIGNATURE = [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C].freeze
|
|
25
|
+
|
|
26
|
+
# RAR5 format signature: "Rar!\x1A\x07\x01\x00"
|
|
27
|
+
RAR5_SIGNATURE = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00].freeze
|
|
28
|
+
|
|
29
|
+
# RAR4 format signature: "Rar!\x1A\x07\x00"
|
|
30
|
+
RAR4_SIGNATURE = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00].freeze
|
|
31
|
+
|
|
32
|
+
# ZIP format signature: "PK\x03\x04"
|
|
33
|
+
ZIP_SIGNATURE = [0x50, 0x4B, 0x03, 0x04].freeze
|
|
34
|
+
|
|
35
|
+
# GZIP format signature: "\x1F\x8B"
|
|
36
|
+
GZIP_SIGNATURE = [0x1F, 0x8B].freeze
|
|
37
|
+
|
|
38
|
+
# BZIP2 format signature: "BZ"
|
|
39
|
+
BZIP2_SIGNATURE = [0x42, 0x5A].freeze
|
|
40
|
+
|
|
41
|
+
# Detect archive format from file path
|
|
42
|
+
#
|
|
43
|
+
# @param file_path [String] Path to the archive file
|
|
44
|
+
# @return [Symbol, nil] Format identifier (:xz, :seven_zip, :rar5, :rar4,
|
|
45
|
+
# :zip, :gzip, :bzip2, :lzma_alone) or nil if unknown
|
|
46
|
+
def self.detect(file_path)
|
|
47
|
+
return nil unless File.exist?(file_path)
|
|
48
|
+
|
|
49
|
+
header = File.binread(file_path, 16)
|
|
50
|
+
return nil if header.nil? || header.empty?
|
|
51
|
+
|
|
52
|
+
bytes = header.bytes
|
|
53
|
+
|
|
54
|
+
case bytes
|
|
55
|
+
in [0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00, *]
|
|
56
|
+
:xz
|
|
57
|
+
in [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C, *]
|
|
58
|
+
:seven_zip
|
|
59
|
+
in [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00, *]
|
|
60
|
+
:rar5
|
|
61
|
+
in [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00, *]
|
|
62
|
+
:rar4
|
|
63
|
+
in [0x50, 0x4B, 0x03, 0x04, *]
|
|
64
|
+
:zip
|
|
65
|
+
in [0x1F, 0x8B, *]
|
|
66
|
+
:gzip
|
|
67
|
+
in [0x42, 0x5A, *]
|
|
68
|
+
:bzip2
|
|
69
|
+
else
|
|
70
|
+
# Check for LZMA_Alone format (13-byte header with properties)
|
|
71
|
+
detect_lzma_alone(bytes)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Check if file is XZ Utils format
|
|
76
|
+
#
|
|
77
|
+
# @param file_path [String] Path to the file
|
|
78
|
+
# @return [Boolean] true if XZ format
|
|
79
|
+
def self.xz?(file_path)
|
|
80
|
+
detect(file_path) == :xz
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Check if file is 7-Zip format
|
|
84
|
+
#
|
|
85
|
+
# @param file_path [String] Path to the file
|
|
86
|
+
# @return [Boolean] true if 7-Zip format
|
|
87
|
+
def self.seven_zip?(file_path)
|
|
88
|
+
detect(file_path) == :seven_zip
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Check if file is RAR5 format
|
|
92
|
+
#
|
|
93
|
+
# @param file_path [String] Path to the file
|
|
94
|
+
# @return [Boolean] true if RAR5 format
|
|
95
|
+
def self.rar5?(file_path)
|
|
96
|
+
detect(file_path) == :rar5
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Check if file is RAR4 format
|
|
100
|
+
#
|
|
101
|
+
# @param file_path [String] Path to the file
|
|
102
|
+
# @return [Boolean] true if RAR4 format
|
|
103
|
+
def self.rar4?(file_path)
|
|
104
|
+
detect(file_path) == :rar4
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Mapping of detected format symbols to (extension, constant-path)
|
|
108
|
+
# tuples. The constant path is resolved lazily so autoload fires
|
|
109
|
+
# only when a format is actually requested.
|
|
110
|
+
READER_FOR_FORMAT = {
|
|
111
|
+
xz: ["omnizip/formats/xz", "Omnizip::Formats::Xz"],
|
|
112
|
+
seven_zip: ["omnizip/formats/seven_zip", "Omnizip::Formats::SevenZip::Reader"],
|
|
113
|
+
rar5: ["omnizip/formats/rar5", "Omnizip::Formats::Rar5::Reader"],
|
|
114
|
+
rar4: ["omnizip/formats/rar3", "Omnizip::Formats::Rar3::Reader"],
|
|
115
|
+
zip: ["omnizip/formats/zip", "Omnizip::Formats::Zip::Reader"],
|
|
116
|
+
gzip: ["omnizip/formats/gzip", "Omnizip::Formats::Gzip"],
|
|
117
|
+
bzip2: ["omnizip/formats/bzip2_file", "Omnizip::Formats::Bzip2File"],
|
|
118
|
+
}.freeze
|
|
119
|
+
|
|
120
|
+
# Get the appropriate reader class for the format
|
|
121
|
+
#
|
|
122
|
+
# @param file_path [String] Path to the archive file
|
|
123
|
+
# @return [Class, nil] Reader class or nil if unknown format
|
|
124
|
+
def self.reader_for(file_path)
|
|
125
|
+
format = detect(file_path)
|
|
126
|
+
return nil unless format
|
|
127
|
+
|
|
128
|
+
mapping = READER_FOR_FORMAT[format]
|
|
129
|
+
return nil unless mapping
|
|
130
|
+
|
|
131
|
+
_path, const_path = mapping
|
|
132
|
+
Object.const_get(const_path)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Detect LZMA_Alone format
|
|
136
|
+
#
|
|
137
|
+
# LZMA_Alone format has a 13-byte header:
|
|
138
|
+
# - 1 byte: properties (lc, lp, pb encoded)
|
|
139
|
+
# - 4 bytes: dictionary size (little-endian)
|
|
140
|
+
# - 8 bytes: uncompressed size (little-endian, -1 for unknown)
|
|
141
|
+
#
|
|
142
|
+
# @param bytes [Array<Integer>] First bytes of file
|
|
143
|
+
# @return [Symbol, nil] :lzma_alone or nil
|
|
144
|
+
def self.detect_lzma_alone(bytes)
|
|
145
|
+
return nil if bytes.size < 13
|
|
146
|
+
|
|
147
|
+
# Check properties byte (must be valid lc/lp/pb encoding)
|
|
148
|
+
props = bytes[0]
|
|
149
|
+
return nil if props > 225 # Max valid value is (9 * 5 * 5) - 1 = 224
|
|
150
|
+
|
|
151
|
+
lc = props % 9
|
|
152
|
+
lp = (props / 9) % 5
|
|
153
|
+
pb = props / 45
|
|
154
|
+
|
|
155
|
+
# Validate ranges
|
|
156
|
+
return nil if lc > 8 || lp > 4 || pb > 4
|
|
157
|
+
|
|
158
|
+
# Dictionary size should be power of 2 or close to it
|
|
159
|
+
dict_size = bytes[1, 4].pack("C*").unpack1("V")
|
|
160
|
+
return nil if dict_size.zero? || dict_size > (1 << 30) # Max ~1GB
|
|
161
|
+
|
|
162
|
+
:lzma_alone
|
|
163
|
+
end
|
|
164
|
+
private_class_method :detect_lzma_alone
|
|
165
|
+
end
|
|
166
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Formats
|
|
7
|
+
# BZIP2 file format
|
|
8
|
+
#
|
|
9
|
+
# BZIP2 is a file compression format that uses the BZip2 algorithm
|
|
10
|
+
# with block-sorting compression (Burrows-Wheeler Transform).
|
|
11
|
+
#
|
|
12
|
+
# Format structure:
|
|
13
|
+
# - Magic bytes: "BZh" (0x42 0x5A 0x68)
|
|
14
|
+
# - Block size indicator: '1'-'9' (100KB - 900KB)
|
|
15
|
+
# - Compressed blocks
|
|
16
|
+
# - End-of-stream marker
|
|
17
|
+
#
|
|
18
|
+
# The format supports multiple compressed blocks, each with its own
|
|
19
|
+
# CRC32 checksum for data integrity verification.
|
|
20
|
+
module Bzip2File
|
|
21
|
+
# BZIP2 magic bytes
|
|
22
|
+
BZIP2_MAGIC = "BZh"
|
|
23
|
+
|
|
24
|
+
# Block size markers ('1' to '9')
|
|
25
|
+
BLOCK_SIZE_MIN = 1
|
|
26
|
+
BLOCK_SIZE_MAX = 9
|
|
27
|
+
|
|
28
|
+
# Stream markers
|
|
29
|
+
STREAM_MAGIC = 0x314159265359 # π in hex
|
|
30
|
+
BLOCK_MAGIC = 0x177245385090 # Block start marker
|
|
31
|
+
STREAM_END_MAGIC = 0x177245385090 # Stream end marker
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
# Compress a file with BZIP2
|
|
35
|
+
#
|
|
36
|
+
# @param input_path [String] Input file path
|
|
37
|
+
# @param output_path [String] Output BZIP2 file path
|
|
38
|
+
# @param options [Hash] Compression options
|
|
39
|
+
# @option options [Integer] :level Compression level (1-9)
|
|
40
|
+
def compress(input_path, output_path, options = {})
|
|
41
|
+
input_data = File.binread(input_path)
|
|
42
|
+
|
|
43
|
+
File.open(output_path, "wb") do |output|
|
|
44
|
+
compress_stream(StringIO.new(input_data), output, options)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Decompress a BZIP2 file
|
|
49
|
+
#
|
|
50
|
+
# @param input_path [String] Input BZIP2 file path
|
|
51
|
+
# @param output_path [String] Output file path
|
|
52
|
+
def decompress(input_path, output_path)
|
|
53
|
+
File.open(input_path, "rb") do |input|
|
|
54
|
+
File.open(output_path, "wb") do |output|
|
|
55
|
+
decompress_stream(input, output)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Compress data stream with BZIP2
|
|
61
|
+
#
|
|
62
|
+
# @param input_io [IO] Input stream
|
|
63
|
+
# @param output_io [IO] Output stream
|
|
64
|
+
# @param options [Hash] Compression options
|
|
65
|
+
def compress_stream(input_io, output_io, options = {})
|
|
66
|
+
level = options[:level] || 9
|
|
67
|
+
level = level.clamp(BLOCK_SIZE_MIN, BLOCK_SIZE_MAX)
|
|
68
|
+
|
|
69
|
+
input_data = input_io.read
|
|
70
|
+
|
|
71
|
+
# Write BZIP2 header
|
|
72
|
+
write_header(output_io, level)
|
|
73
|
+
|
|
74
|
+
# Get BZip2 algorithm
|
|
75
|
+
bzip2 = AlgorithmRegistry.get(:bzip2).new
|
|
76
|
+
|
|
77
|
+
# Compress data
|
|
78
|
+
compressed_io = StringIO.new
|
|
79
|
+
compressed_io.set_encoding(Encoding::BINARY)
|
|
80
|
+
|
|
81
|
+
bzip2.compress(
|
|
82
|
+
StringIO.new(input_data),
|
|
83
|
+
compressed_io,
|
|
84
|
+
build_compression_options(level),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Write compressed data
|
|
88
|
+
compressed_io.rewind
|
|
89
|
+
compressed_data = compressed_io.read
|
|
90
|
+
output_io.write(compressed_data)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Decompress BZIP2 stream
|
|
94
|
+
#
|
|
95
|
+
# @param input_io [IO] Input stream
|
|
96
|
+
# @param output_io [IO] Output stream
|
|
97
|
+
def decompress_stream(input_io, output_io)
|
|
98
|
+
# Read and verify header
|
|
99
|
+
read_header(input_io)
|
|
100
|
+
|
|
101
|
+
# Get BZip2 algorithm
|
|
102
|
+
bzip2 = AlgorithmRegistry.get(:bzip2).new
|
|
103
|
+
|
|
104
|
+
# Decompress data
|
|
105
|
+
decompressed_io = StringIO.new
|
|
106
|
+
decompressed_io.set_encoding(Encoding::BINARY)
|
|
107
|
+
|
|
108
|
+
bzip2.decompress(input_io, decompressed_io)
|
|
109
|
+
|
|
110
|
+
# Write decompressed data
|
|
111
|
+
decompressed_io.rewind
|
|
112
|
+
output_io.write(decompressed_io.read)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
# Write BZIP2 header
|
|
118
|
+
#
|
|
119
|
+
# @param output [IO] Output stream
|
|
120
|
+
# @param level [Integer] Compression level (1-9)
|
|
121
|
+
def write_header(output, level)
|
|
122
|
+
# BZIP2 magic: "BZh" + block size
|
|
123
|
+
header = "#{BZIP2_MAGIC}#{level}"
|
|
124
|
+
output.write(header)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Read BZIP2 header
|
|
128
|
+
#
|
|
129
|
+
# @param input [IO] Input stream
|
|
130
|
+
# @return [Integer] Block size level
|
|
131
|
+
def read_header(input)
|
|
132
|
+
magic = input.read(3)
|
|
133
|
+
unless magic == BZIP2_MAGIC
|
|
134
|
+
raise Error, "Not a BZIP2 file (invalid magic bytes)"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
level_char = input.read(1)
|
|
138
|
+
level = level_char.to_i
|
|
139
|
+
|
|
140
|
+
unless level.between?(BLOCK_SIZE_MIN, BLOCK_SIZE_MAX)
|
|
141
|
+
raise Error, "Invalid BZIP2 block size: #{level_char}"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
level
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Build compression options
|
|
148
|
+
#
|
|
149
|
+
# @param level [Integer] Compression level
|
|
150
|
+
# @return [Object] Compression options
|
|
151
|
+
def build_compression_options(level)
|
|
152
|
+
Models::CompressionOptions.new.tap do |opts|
|
|
153
|
+
opts.level = level
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Cpio
|
|
6
|
+
# IO wrapper that limits reading to a specific byte count
|
|
7
|
+
#
|
|
8
|
+
# Used to read file content from CPIO archives where the file size
|
|
9
|
+
# is known in advance but the underlying IO stream continues.
|
|
10
|
+
class BoundedIO
|
|
11
|
+
attr_reader :length, :remaining
|
|
12
|
+
|
|
13
|
+
# Initialize bounded IO
|
|
14
|
+
#
|
|
15
|
+
# @param io [IO] Underlying IO stream
|
|
16
|
+
# @param length [Integer] Maximum bytes to read
|
|
17
|
+
# @yield Block called when EOF is reached (for reading padding)
|
|
18
|
+
def initialize(io, length, &eof_callback)
|
|
19
|
+
@io = io
|
|
20
|
+
@length = length
|
|
21
|
+
@remaining = length
|
|
22
|
+
@eof_callback = eof_callback
|
|
23
|
+
@eof = false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Read bytes from the IO
|
|
27
|
+
#
|
|
28
|
+
# @param size [Integer, nil] Number of bytes to read (nil = remaining)
|
|
29
|
+
# @return [String, nil] Data read or nil at EOF
|
|
30
|
+
def read(size = nil)
|
|
31
|
+
return nil if eof?
|
|
32
|
+
|
|
33
|
+
size = @remaining if size.nil?
|
|
34
|
+
data = @io.read(size)
|
|
35
|
+
return nil if data.nil?
|
|
36
|
+
|
|
37
|
+
@remaining -= data.bytesize
|
|
38
|
+
eof?
|
|
39
|
+
data
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# System read (raises on EOF)
|
|
43
|
+
#
|
|
44
|
+
# @param size [Integer] Number of bytes to read
|
|
45
|
+
# @return [String] Data read
|
|
46
|
+
# @raise [EOFError] If at end of bounded region
|
|
47
|
+
def sysread(size)
|
|
48
|
+
raise EOFError, "end of file reached" if eof?
|
|
49
|
+
|
|
50
|
+
read(size)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Check if at end of bounded region
|
|
54
|
+
#
|
|
55
|
+
# @return [Boolean] True if no more bytes to read
|
|
56
|
+
def eof?
|
|
57
|
+
return false if @remaining.positive?
|
|
58
|
+
return @eof if @eof
|
|
59
|
+
|
|
60
|
+
@eof_callback&.call
|
|
61
|
+
@eof = true
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|