omnizip 0.4.7-arm-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,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Algorithms
|
|
7
|
+
class Deflate64
|
|
8
|
+
# Deflate64 encoder
|
|
9
|
+
class Encoder
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :window_size
|
|
13
|
+
|
|
14
|
+
def initialize(output_stream, options = {})
|
|
15
|
+
@output_stream = output_stream
|
|
16
|
+
@window_size = options[:window_size] || DICTIONARY_SIZE
|
|
17
|
+
@compression_level = options[:level] || 6
|
|
18
|
+
@lz77_encoder = LZ77Encoder.new(@window_size)
|
|
19
|
+
@huffman = HuffmanCoder.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Compress input stream to output stream
|
|
23
|
+
#
|
|
24
|
+
# @param input_stream [IO] Input data stream
|
|
25
|
+
def compress(input_stream)
|
|
26
|
+
data = input_stream.read
|
|
27
|
+
|
|
28
|
+
# Step 1: LZ77 compression with 64KB window
|
|
29
|
+
tokens = @lz77_encoder.find_matches(data)
|
|
30
|
+
|
|
31
|
+
# Step 2: Huffman coding
|
|
32
|
+
compressed = @huffman.encode(tokens)
|
|
33
|
+
|
|
34
|
+
# Step 3: Serialize trees and write to output
|
|
35
|
+
output = serialize_with_trees(
|
|
36
|
+
compressed,
|
|
37
|
+
@huffman.literal_tree,
|
|
38
|
+
@huffman.distance_tree,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
@output_stream.write(output)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
# Serialize compressed data with Huffman trees
|
|
47
|
+
#
|
|
48
|
+
# @param compressed [String] Compressed data
|
|
49
|
+
# @param literal_tree [Hash] Literal Huffman tree
|
|
50
|
+
# @param distance_tree [Hash] Distance Huffman tree
|
|
51
|
+
# @return [String] Serialized output
|
|
52
|
+
def serialize_with_trees(compressed, literal_tree, distance_tree)
|
|
53
|
+
literal_json = literal_tree.to_json
|
|
54
|
+
distance_json = distance_tree.to_json
|
|
55
|
+
|
|
56
|
+
# Pack: literal_size (4 bytes), distance_size (4 bytes),
|
|
57
|
+
# literal_tree, distance_tree, compressed_data
|
|
58
|
+
[
|
|
59
|
+
literal_json.bytesize,
|
|
60
|
+
distance_json.bytesize,
|
|
61
|
+
literal_json,
|
|
62
|
+
distance_json,
|
|
63
|
+
compressed,
|
|
64
|
+
].pack("NNA#{literal_json.bytesize}A#{distance_json.bytesize}A*")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Encode data block
|
|
68
|
+
#
|
|
69
|
+
# @param data [String] Input data
|
|
70
|
+
# @return [String] Compressed data
|
|
71
|
+
def encode_block(data)
|
|
72
|
+
# Find LZ77 matches
|
|
73
|
+
tokens = @lz77_encoder.find_matches(data)
|
|
74
|
+
|
|
75
|
+
# Huffman encode
|
|
76
|
+
@huffman.encode(tokens)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Encode stream in chunks
|
|
80
|
+
#
|
|
81
|
+
# @param input_stream [IO] Input stream
|
|
82
|
+
# @param chunk_size [Integer] Size of chunks to process
|
|
83
|
+
def encode_stream(input_stream, chunk_size = 65_536)
|
|
84
|
+
until input_stream.eof?
|
|
85
|
+
chunk = input_stream.read(chunk_size)
|
|
86
|
+
break if chunk.nil? || chunk.empty?
|
|
87
|
+
|
|
88
|
+
compressed = encode_block(chunk)
|
|
89
|
+
@output_stream.write(compressed)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Algorithms
|
|
5
|
+
class Deflate64
|
|
6
|
+
# Huffman coding for Deflate64
|
|
7
|
+
class HuffmanCoder
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
# Length code mapping
|
|
11
|
+
LENGTH_CODES_MAP = {
|
|
12
|
+
3 => 257, 4 => 258, 5 => 259, 6 => 260, 7 => 261,
|
|
13
|
+
8 => 262, 9 => 263, 10 => 264, 11 => 265, 12 => 266,
|
|
14
|
+
13 => 267, 14 => 268, 15 => 269, 16 => 270, 17 => 271,
|
|
15
|
+
18 => 272, 19 => 273, 20 => 274, 21 => 275, 22 => 276,
|
|
16
|
+
23 => 277, 24 => 278, 25 => 279, 26 => 280, 27 => 281,
|
|
17
|
+
28 => 282, 29 => 283, 30 => 284, 31 => 285
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
# Distance code mapping
|
|
21
|
+
DISTANCE_CODES_MAP = (0..29).to_a.freeze
|
|
22
|
+
|
|
23
|
+
attr_reader :literal_tree, :distance_tree
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
@literal_tree = nil
|
|
27
|
+
@distance_tree = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Encode tokens using Huffman coding
|
|
31
|
+
#
|
|
32
|
+
# @param tokens [Array<Hash>] LZ77 tokens
|
|
33
|
+
# @return [String] Encoded bitstream
|
|
34
|
+
def encode(tokens)
|
|
35
|
+
# Build frequency tables
|
|
36
|
+
literal_freqs = build_literal_frequencies(tokens)
|
|
37
|
+
distance_freqs = build_distance_frequencies(tokens)
|
|
38
|
+
|
|
39
|
+
# Build Huffman trees
|
|
40
|
+
@literal_tree = build_tree(literal_freqs)
|
|
41
|
+
@distance_tree = build_tree(distance_freqs)
|
|
42
|
+
|
|
43
|
+
# Encode tokens
|
|
44
|
+
encode_tokens(tokens)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Decode bitstream using Huffman coding
|
|
48
|
+
#
|
|
49
|
+
# @param bitstream [String] Encoded data
|
|
50
|
+
# @param literal_tree [Hash] Literal Huffman tree
|
|
51
|
+
# @param distance_tree [Hash] Distance Huffman tree
|
|
52
|
+
# @return [Array<Hash>] Decoded tokens
|
|
53
|
+
def decode(bitstream, literal_tree, distance_tree)
|
|
54
|
+
@literal_tree = literal_tree
|
|
55
|
+
@distance_tree = distance_tree
|
|
56
|
+
|
|
57
|
+
decode_tokens(bitstream)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
# Build frequency table for literals and lengths
|
|
63
|
+
#
|
|
64
|
+
# @param tokens [Array<Hash>] LZ77 tokens
|
|
65
|
+
# @return [Hash] Frequency table
|
|
66
|
+
def build_literal_frequencies(tokens)
|
|
67
|
+
freqs = Hash.new(0)
|
|
68
|
+
|
|
69
|
+
tokens.each do |token|
|
|
70
|
+
if token[:type] == :literal
|
|
71
|
+
freqs[token[:value]] += 1
|
|
72
|
+
else
|
|
73
|
+
length_code = length_to_code(token[:length])
|
|
74
|
+
freqs[length_code] += 1
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Add end of block marker
|
|
79
|
+
freqs[END_OF_BLOCK] = 1
|
|
80
|
+
|
|
81
|
+
freqs
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Build frequency table for distances
|
|
85
|
+
#
|
|
86
|
+
# @param tokens [Array<Hash>] LZ77 tokens
|
|
87
|
+
# @return [Hash] Frequency table
|
|
88
|
+
def build_distance_frequencies(tokens)
|
|
89
|
+
freqs = Hash.new(0)
|
|
90
|
+
|
|
91
|
+
tokens.each do |token|
|
|
92
|
+
next unless token[:type] == :match
|
|
93
|
+
|
|
94
|
+
distance_code = distance_to_code(token[:distance])
|
|
95
|
+
freqs[distance_code] += 1
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
freqs
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Build Huffman tree from frequencies
|
|
102
|
+
#
|
|
103
|
+
# @param frequencies [Hash] Symbol frequencies
|
|
104
|
+
# @return [Hash] Huffman code table
|
|
105
|
+
def build_tree(frequencies)
|
|
106
|
+
return {} if frequencies.empty?
|
|
107
|
+
|
|
108
|
+
# Build priority queue of nodes
|
|
109
|
+
nodes = frequencies.map do |symbol, freq|
|
|
110
|
+
{ symbol: symbol, freq: freq, left: nil, right: nil }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Build tree using priority queue
|
|
114
|
+
while nodes.size > 1
|
|
115
|
+
nodes.sort_by! { |n| n[:freq] }
|
|
116
|
+
left = nodes.shift
|
|
117
|
+
right = nodes.shift
|
|
118
|
+
|
|
119
|
+
parent = {
|
|
120
|
+
symbol: nil,
|
|
121
|
+
freq: left[:freq] + right[:freq],
|
|
122
|
+
left: left,
|
|
123
|
+
right: right,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
nodes << parent
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Generate codes from tree
|
|
130
|
+
generate_codes(nodes.first)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Generate Huffman codes from tree
|
|
134
|
+
#
|
|
135
|
+
# @param node [Hash] Tree node
|
|
136
|
+
# @param code [String] Current code
|
|
137
|
+
# @param codes [Hash] Code table
|
|
138
|
+
# @return [Hash] Complete code table
|
|
139
|
+
def generate_codes(node, code = "", codes = {})
|
|
140
|
+
return codes if node.nil?
|
|
141
|
+
|
|
142
|
+
if node[:symbol]
|
|
143
|
+
codes[node[:symbol]] = code
|
|
144
|
+
else
|
|
145
|
+
generate_codes(node[:left], "#{code}0", codes)
|
|
146
|
+
generate_codes(node[:right], "#{code}1", codes)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
codes
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Encode tokens to bitstream
|
|
153
|
+
#
|
|
154
|
+
# @param tokens [Array<Hash>] LZ77 tokens
|
|
155
|
+
# @return [String] Encoded bitstream
|
|
156
|
+
def encode_tokens(tokens)
|
|
157
|
+
bits = ""
|
|
158
|
+
|
|
159
|
+
tokens.each do |token|
|
|
160
|
+
if token[:type] == :literal
|
|
161
|
+
bits += @literal_tree[token[:value]]
|
|
162
|
+
else
|
|
163
|
+
length_code = length_to_code(token[:length])
|
|
164
|
+
bits += @literal_tree[length_code]
|
|
165
|
+
|
|
166
|
+
distance_code = distance_to_code(token[:distance])
|
|
167
|
+
bits += @distance_tree[distance_code]
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Add end of block marker
|
|
172
|
+
bits += @literal_tree[END_OF_BLOCK]
|
|
173
|
+
|
|
174
|
+
# Convert bits to bytes
|
|
175
|
+
bits_to_bytes(bits)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Decode tokens from bitstream
|
|
179
|
+
#
|
|
180
|
+
# @param bitstream [String] Encoded data
|
|
181
|
+
# @return [Array<Hash>] Decoded tokens
|
|
182
|
+
def decode_tokens(bitstream)
|
|
183
|
+
tokens = []
|
|
184
|
+
bits = bytes_to_bits(bitstream)
|
|
185
|
+
pos = 0
|
|
186
|
+
|
|
187
|
+
while pos < bits.length
|
|
188
|
+
symbol, length = decode_symbol(bits, pos, @literal_tree)
|
|
189
|
+
|
|
190
|
+
# Check for decoding failure
|
|
191
|
+
if symbol.nil?
|
|
192
|
+
raise Omnizip::DecompressionError,
|
|
193
|
+
"Failed to decode symbol at bit position #{pos}"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
pos += length
|
|
197
|
+
|
|
198
|
+
break if symbol == END_OF_BLOCK
|
|
199
|
+
|
|
200
|
+
if symbol < 256
|
|
201
|
+
tokens << { type: :literal, value: symbol }
|
|
202
|
+
else
|
|
203
|
+
match_length = code_to_length(symbol)
|
|
204
|
+
|
|
205
|
+
dist_symbol, dist_length =
|
|
206
|
+
decode_symbol(bits, pos, @distance_tree)
|
|
207
|
+
|
|
208
|
+
# Check for distance decoding failure
|
|
209
|
+
if dist_symbol.nil?
|
|
210
|
+
raise Omnizip::DecompressionError,
|
|
211
|
+
"Failed to decode distance at bit position #{pos}"
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
pos += dist_length
|
|
215
|
+
|
|
216
|
+
distance = code_to_distance(dist_symbol)
|
|
217
|
+
|
|
218
|
+
tokens << {
|
|
219
|
+
type: :match,
|
|
220
|
+
length: match_length,
|
|
221
|
+
distance: distance,
|
|
222
|
+
}
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
tokens
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Decode single symbol from bitstream
|
|
230
|
+
#
|
|
231
|
+
# @param bits [String] Bit string
|
|
232
|
+
# @param pos [Integer] Current position
|
|
233
|
+
# @param tree [Hash] Huffman tree
|
|
234
|
+
# @return [Array] Symbol and bits consumed
|
|
235
|
+
def decode_symbol(bits, pos, tree)
|
|
236
|
+
code = ""
|
|
237
|
+
reverse_tree = tree.invert
|
|
238
|
+
|
|
239
|
+
while pos < bits.length
|
|
240
|
+
code += bits[pos]
|
|
241
|
+
pos += 1
|
|
242
|
+
|
|
243
|
+
if reverse_tree[code]
|
|
244
|
+
return [reverse_tree[code], code.length]
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
[nil, 0]
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Convert match length to Huffman code
|
|
252
|
+
def length_to_code(length)
|
|
253
|
+
LENGTH_CODES_MAP[length] || 285
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Convert Huffman code to match length
|
|
257
|
+
def code_to_length(code)
|
|
258
|
+
LENGTH_CODES_MAP.key(code) || 258
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Convert distance to Huffman code
|
|
262
|
+
# Uses DEFLATE distance code table
|
|
263
|
+
def distance_to_code(distance)
|
|
264
|
+
case distance
|
|
265
|
+
when 1..4
|
|
266
|
+
distance - 1
|
|
267
|
+
when 5..8
|
|
268
|
+
4 + ((distance - 5) / 2)
|
|
269
|
+
when 9..16
|
|
270
|
+
6 + ((distance - 9) / 4)
|
|
271
|
+
when 17..32
|
|
272
|
+
8 + ((distance - 17) / 8)
|
|
273
|
+
when 33..64
|
|
274
|
+
10 + ((distance - 33) / 16)
|
|
275
|
+
when 65..128
|
|
276
|
+
12 + ((distance - 65) / 32)
|
|
277
|
+
when 129..256
|
|
278
|
+
14 + ((distance - 129) / 64)
|
|
279
|
+
when 257..512
|
|
280
|
+
16 + ((distance - 257) / 128)
|
|
281
|
+
when 513..1024
|
|
282
|
+
18 + ((distance - 513) / 256)
|
|
283
|
+
when 1025..2048
|
|
284
|
+
20 + ((distance - 1025) / 512)
|
|
285
|
+
when 2049..4096
|
|
286
|
+
22 + ((distance - 2049) / 1024)
|
|
287
|
+
when 4097..8192
|
|
288
|
+
24 + ((distance - 4097) / 2048)
|
|
289
|
+
when 8193..16384
|
|
290
|
+
26 + ((distance - 8193) / 4096)
|
|
291
|
+
when 16385..32768
|
|
292
|
+
28 + ((distance - 16385) / 8192)
|
|
293
|
+
when 32769..65536
|
|
294
|
+
29
|
|
295
|
+
else
|
|
296
|
+
29 # Max distance code for 64KB window
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Convert Huffman code to distance
|
|
301
|
+
# Uses DEFLATE distance code table (base distances)
|
|
302
|
+
def code_to_distance(code)
|
|
303
|
+
case code
|
|
304
|
+
when 0..3
|
|
305
|
+
code + 1
|
|
306
|
+
when 4..5
|
|
307
|
+
5 + ((code - 4) * 2)
|
|
308
|
+
when 6..7
|
|
309
|
+
9 + ((code - 6) * 4)
|
|
310
|
+
when 8..9
|
|
311
|
+
17 + ((code - 8) * 8)
|
|
312
|
+
when 10..11
|
|
313
|
+
33 + ((code - 10) * 16)
|
|
314
|
+
when 12..13
|
|
315
|
+
65 + ((code - 12) * 32)
|
|
316
|
+
when 14..15
|
|
317
|
+
129 + ((code - 14) * 64)
|
|
318
|
+
when 16..17
|
|
319
|
+
257 + ((code - 16) * 128)
|
|
320
|
+
when 18..19
|
|
321
|
+
513 + ((code - 18) * 256)
|
|
322
|
+
when 20..21
|
|
323
|
+
1025 + ((code - 20) * 512)
|
|
324
|
+
when 22..23
|
|
325
|
+
2049 + ((code - 22) * 1024)
|
|
326
|
+
when 24..25
|
|
327
|
+
4097 + ((code - 24) * 2048)
|
|
328
|
+
when 26..27
|
|
329
|
+
8193 + ((code - 26) * 4096)
|
|
330
|
+
when 28..29
|
|
331
|
+
16385 + ((code - 28) * 8192)
|
|
332
|
+
else
|
|
333
|
+
1 # Default to distance 1
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# Convert bit string to bytes
|
|
338
|
+
def bits_to_bytes(bits)
|
|
339
|
+
bytes = bits.scan(/.{1,8}/).map do |byte_bits|
|
|
340
|
+
byte_bits.ljust(8, "0").to_i(2)
|
|
341
|
+
end
|
|
342
|
+
bytes.pack("C*")
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Convert bytes to bit string
|
|
346
|
+
def bytes_to_bits(bytes)
|
|
347
|
+
bytes.unpack("C*").map { |b| b.to_s(2).rjust(8, "0") }.join
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Algorithms
|
|
5
|
+
class Deflate64
|
|
6
|
+
# LZ77 encoder with 64KB sliding window for Deflate64
|
|
7
|
+
class LZ77Encoder
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :window_size
|
|
11
|
+
|
|
12
|
+
def initialize(window_size = DICTIONARY_SIZE)
|
|
13
|
+
@window_size = window_size
|
|
14
|
+
@window = []
|
|
15
|
+
@hash_table = {}
|
|
16
|
+
@position = 0
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Find matches in data and return array of literals and match tokens
|
|
20
|
+
#
|
|
21
|
+
# @param data [String] Input data to compress
|
|
22
|
+
# @return [Array<Hash>] Array of match tokens
|
|
23
|
+
def find_matches(data)
|
|
24
|
+
tokens = []
|
|
25
|
+
pos = 0
|
|
26
|
+
|
|
27
|
+
while pos < data.bytesize
|
|
28
|
+
match = find_longest_match(pos, data)
|
|
29
|
+
|
|
30
|
+
if match && match[:length] >= MIN_MATCH_LENGTH
|
|
31
|
+
tokens << {
|
|
32
|
+
type: :match,
|
|
33
|
+
length: match[:length],
|
|
34
|
+
distance: match[:distance],
|
|
35
|
+
}
|
|
36
|
+
pos += match[:length]
|
|
37
|
+
else
|
|
38
|
+
tokens << {
|
|
39
|
+
type: :literal,
|
|
40
|
+
value: data.getbyte(pos),
|
|
41
|
+
}
|
|
42
|
+
pos += 1
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
update_window(data, pos)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
tokens
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
# Find longest match for current position
|
|
54
|
+
#
|
|
55
|
+
# @param pos [Integer] Current position in data
|
|
56
|
+
# @param data [String] Input data
|
|
57
|
+
# @return [Hash, nil] Match information or nil
|
|
58
|
+
def find_longest_match(pos, data)
|
|
59
|
+
return nil if pos + MIN_MATCH_LENGTH > data.bytesize
|
|
60
|
+
|
|
61
|
+
best_match = nil
|
|
62
|
+
best_length = MIN_MATCH_LENGTH - 1
|
|
63
|
+
|
|
64
|
+
# Calculate hash for current position
|
|
65
|
+
hash = calculate_hash(data, pos)
|
|
66
|
+
candidates = @hash_table[hash] || []
|
|
67
|
+
|
|
68
|
+
# Search through candidate matches
|
|
69
|
+
candidates.reverse.take(MAX_CHAIN_LENGTH).each do |candidate_pos|
|
|
70
|
+
distance = pos - candidate_pos
|
|
71
|
+
break if distance > MAX_DISTANCE
|
|
72
|
+
|
|
73
|
+
# Find match length
|
|
74
|
+
length = match_length(data, pos, candidate_pos)
|
|
75
|
+
|
|
76
|
+
if length > best_length
|
|
77
|
+
best_length = length
|
|
78
|
+
best_match = {
|
|
79
|
+
length: length,
|
|
80
|
+
distance: distance,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
break if length >= NICE_MATCH
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Add current position to hash table
|
|
88
|
+
@hash_table[hash] ||= []
|
|
89
|
+
@hash_table[hash] << pos
|
|
90
|
+
|
|
91
|
+
best_match
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Calculate match length between two positions
|
|
95
|
+
#
|
|
96
|
+
# @param data [String] Input data
|
|
97
|
+
# @param pos1 [Integer] First position
|
|
98
|
+
# @param pos2 [Integer] Second position
|
|
99
|
+
# @return [Integer] Match length
|
|
100
|
+
def match_length(data, pos1, pos2)
|
|
101
|
+
max_length = [MAX_MATCH_LENGTH, data.bytesize - pos1].min
|
|
102
|
+
length = 0
|
|
103
|
+
|
|
104
|
+
while length < max_length &&
|
|
105
|
+
data.getbyte(pos1 + length) == data.getbyte(pos2 + length)
|
|
106
|
+
length += 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
length
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Calculate hash value for position
|
|
113
|
+
#
|
|
114
|
+
# @param data [String] Input data
|
|
115
|
+
# @param pos [Integer] Position to hash
|
|
116
|
+
# @return [Integer] Hash value
|
|
117
|
+
def calculate_hash(data, pos)
|
|
118
|
+
return 0 if pos + MIN_MATCH_LENGTH > data.bytesize
|
|
119
|
+
|
|
120
|
+
hash = 0
|
|
121
|
+
MIN_MATCH_LENGTH.times do |i|
|
|
122
|
+
hash = ((hash << HASH_SHIFT) ^
|
|
123
|
+
data.getbyte(pos + i)) & (HASH_SIZE - 1)
|
|
124
|
+
end
|
|
125
|
+
hash
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Update sliding window
|
|
129
|
+
#
|
|
130
|
+
# @param data [String] Input data
|
|
131
|
+
# @param pos [Integer] Current position
|
|
132
|
+
def update_window(data, pos)
|
|
133
|
+
@window << data.getbyte(pos - 1) if pos.positive?
|
|
134
|
+
@window.shift if @window.size > @window_size
|
|
135
|
+
@position = pos
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zlib"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Algorithms
|
|
7
|
+
# Deflate64 (Enhanced Deflate) compression algorithm
|
|
8
|
+
#
|
|
9
|
+
# Extends standard Deflate with:
|
|
10
|
+
# - 64KB sliding window (vs 32KB)
|
|
11
|
+
# - Better compression for large files
|
|
12
|
+
# - ZIP compression method 9
|
|
13
|
+
#
|
|
14
|
+
# NOTE: This is a simplified implementation that uses standard
|
|
15
|
+
# Deflate internally, as true Deflate64 requires complex
|
|
16
|
+
# bit-level manipulation that is better handled by libraries
|
|
17
|
+
# specifically designed for it.
|
|
18
|
+
class Deflate64 < Algorithm
|
|
19
|
+
# Nested classes - autoloaded
|
|
20
|
+
autoload :Constants, "omnizip/algorithms/deflate64/constants"
|
|
21
|
+
autoload :Decoder, "omnizip/algorithms/deflate64/decoder"
|
|
22
|
+
autoload :Encoder, "omnizip/algorithms/deflate64/encoder"
|
|
23
|
+
autoload :HuffmanCoder, "omnizip/algorithms/deflate64/huffman_coder"
|
|
24
|
+
autoload :Lz77Encoder, "omnizip/algorithms/deflate64/lz77_encoder"
|
|
25
|
+
|
|
26
|
+
# Constants
|
|
27
|
+
DICTIONARY_SIZE = 65_536 # 64KB window
|
|
28
|
+
|
|
29
|
+
# Algorithm metadata
|
|
30
|
+
def self.metadata
|
|
31
|
+
Models::AlgorithmMetadata.new.tap do |meta|
|
|
32
|
+
meta.name = "deflate64"
|
|
33
|
+
meta.description = "Enhanced Deflate with 64KB window"
|
|
34
|
+
meta.version = "1.0.0"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Compress input stream to output stream
|
|
39
|
+
#
|
|
40
|
+
# @param input [IO] Input stream
|
|
41
|
+
# @param output [IO] Output stream
|
|
42
|
+
# @param options [Hash] Compression options
|
|
43
|
+
# @option options [Integer] :level Compression level (1-9)
|
|
44
|
+
def compress(input, output, options = {})
|
|
45
|
+
raw_level = options[:level] || Zlib::DEFAULT_COMPRESSION
|
|
46
|
+
data = input.read
|
|
47
|
+
return if data.nil? || data.empty?
|
|
48
|
+
|
|
49
|
+
# Zlib::DEFAULT_COMPRESSION (-1) maps to the FFI's 6.
|
|
50
|
+
level = raw_level.negative? ? 6 : raw_level.clamp(0, 9)
|
|
51
|
+
compressed = Backends.compress("zlib", data, level) do
|
|
52
|
+
deflater = Zlib::Deflate.new(
|
|
53
|
+
raw_level,
|
|
54
|
+
Zlib::MAX_WBITS,
|
|
55
|
+
Zlib::MAX_MEM_LEVEL,
|
|
56
|
+
)
|
|
57
|
+
result = deflater.deflate(data, Zlib::FINISH)
|
|
58
|
+
deflater.close
|
|
59
|
+
result
|
|
60
|
+
end
|
|
61
|
+
output.write(compressed)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Decompress input stream to output stream
|
|
65
|
+
#
|
|
66
|
+
# @param input [IO] Input stream
|
|
67
|
+
# @param output [IO] Output stream
|
|
68
|
+
# @param options [Hash] Decompression options
|
|
69
|
+
def decompress(input, output, _options = {})
|
|
70
|
+
compressed = input.read
|
|
71
|
+
return if compressed.nil? || compressed.empty?
|
|
72
|
+
|
|
73
|
+
# Set output to binary mode if it's a StringIO
|
|
74
|
+
output.set_encoding(Encoding::BINARY)
|
|
75
|
+
output.binmode
|
|
76
|
+
|
|
77
|
+
# The streams this algorithm produces/consumes are zlib
|
|
78
|
+
# containers (RFC 1950); the Rust "zlib" name speaks exactly
|
|
79
|
+
# that, so the tier swap is byte-transparent.
|
|
80
|
+
decompressed = Backends.decompress("zlib", compressed, Backends::UNKNOWN_LENGTH) do
|
|
81
|
+
inflater = Zlib::Inflate.new(Zlib::MAX_WBITS)
|
|
82
|
+
result = inflater.inflate(compressed)
|
|
83
|
+
inflater.close
|
|
84
|
+
result
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Force binary encoding to match original data
|
|
88
|
+
decompressed.force_encoding(Encoding::BINARY)
|
|
89
|
+
|
|
90
|
+
output.write(decompressed)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Check if streaming is supported
|
|
94
|
+
#
|
|
95
|
+
# @return [Boolean] Always true for Deflate64
|
|
96
|
+
def self.streaming_supported?
|
|
97
|
+
true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Get dictionary size
|
|
101
|
+
#
|
|
102
|
+
# @return [Integer] 64KB
|
|
103
|
+
def self.dictionary_size
|
|
104
|
+
DICTIONARY_SIZE
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Get compression method ID for ZIP format
|
|
108
|
+
#
|
|
109
|
+
# @return [Integer] Method 9
|
|
110
|
+
def self.compression_method
|
|
111
|
+
9
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Register algorithm
|
|
118
|
+
Omnizip::AlgorithmRegistry.register(:deflate64, Omnizip::Algorithms::Deflate64)
|