omnizip 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +754 -0
- data/COPYING +502 -0
- data/Gemfile +17 -0
- data/LICENSE +12 -0
- data/README.adoc +1045 -0
- data/Rakefile +12 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +91 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +271 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +185 -0
- data/docs/getting-started/your-first-archive.adoc +218 -0
- data/docs/guides/advanced-features/encryption.adoc +300 -0
- data/docs/guides/advanced-features/index.adoc +49 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
- data/docs/guides/advanced-features/streaming.adoc +212 -0
- data/docs/guides/archive-formats/gzip-format.adoc +107 -0
- data/docs/guides/archive-formats/index.adoc +130 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
- data/docs/guides/compression-algorithms/deflate.adoc +319 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +398 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
- data/docs/guides/creating-archives.adoc +354 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +218 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +188 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/troubleshooting/index.adoc +208 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +130 -0
- data/lib/omnizip/algorithm_registry.rb +86 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
- data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
- data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
- data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
- data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
- data/lib/omnizip/algorithms/bzip2.rb +130 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
- data/lib/omnizip/algorithms/deflate.rb +128 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
- data/lib/omnizip/algorithms/deflate64.rb +109 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
- data/lib/omnizip/algorithms/lzma.rb +238 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +141 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +116 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +82 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
- data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
- data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
- data/lib/omnizip/algorithms/zstandard.rb +138 -0
- data/lib/omnizip/buffer/memory_archive.rb +251 -0
- data/lib/omnizip/buffer/memory_extractor.rb +224 -0
- data/lib/omnizip/buffer.rb +176 -0
- data/lib/omnizip/checksum_registry.rb +114 -0
- data/lib/omnizip/checksums/crc32.rb +100 -0
- data/lib/omnizip/checksums/crc64.rb +101 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/verifier.rb +131 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +120 -0
- data/lib/omnizip/chunked.rb +129 -0
- data/lib/omnizip/cli/output_formatter.rb +104 -0
- data/lib/omnizip/cli.rb +572 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +427 -0
- data/lib/omnizip/commands/archive_extract_command.rb +272 -0
- data/lib/omnizip/commands/archive_list_command.rb +218 -0
- data/lib/omnizip/commands/archive_repair_command.rb +131 -0
- data/lib/omnizip/commands/archive_verify_command.rb +117 -0
- data/lib/omnizip/commands/compress_command.rb +117 -0
- data/lib/omnizip/commands/decompress_command.rb +120 -0
- data/lib/omnizip/commands/list_command.rb +53 -0
- data/lib/omnizip/commands/metadata_command.rb +153 -0
- data/lib/omnizip/commands/parity_create_command.rb +122 -0
- data/lib/omnizip/commands/parity_repair_command.rb +122 -0
- data/lib/omnizip/commands/parity_verify_command.rb +124 -0
- data/lib/omnizip/commands/profile_list_command.rb +56 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/convenience.rb +359 -0
- data/lib/omnizip/converter/conversion_registry.rb +49 -0
- data/lib/omnizip/converter/conversion_strategy.rb +121 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
- data/lib/omnizip/converter.rb +105 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/error.rb +106 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +63 -0
- data/lib/omnizip/extraction/filter_chain.rb +177 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +240 -0
- data/lib/omnizip/extraction.rb +111 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +113 -0
- data/lib/omnizip/filter.rb +139 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +166 -0
- data/lib/omnizip/filters/bcj.rb +279 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
- data/lib/omnizip/filters/bcj2.rb +99 -0
- data/lib/omnizip/filters/bcj_arm.rb +176 -0
- data/lib/omnizip/filters/bcj_arm64.rb +244 -0
- data/lib/omnizip/filters/bcj_ia64.rb +196 -0
- data/lib/omnizip/filters/bcj_ppc.rb +190 -0
- data/lib/omnizip/filters/bcj_sparc.rb +176 -0
- data/lib/omnizip/filters/bcj_x86.rb +193 -0
- data/lib/omnizip/filters/delta.rb +196 -0
- data/lib/omnizip/filters/filter_base.rb +72 -0
- data/lib/omnizip/filters/registry.rb +123 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/format_detector.rb +162 -0
- data/lib/omnizip/format_registry.rb +59 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +172 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +385 -0
- data/lib/omnizip/formats/cpio/reader.rb +196 -0
- data/lib/omnizip/formats/cpio/writer.rb +234 -0
- data/lib/omnizip/formats/cpio.rb +140 -0
- data/lib/omnizip/formats/format_spec_loader.rb +230 -0
- data/lib/omnizip/formats/gzip.rb +238 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
- data/lib/omnizip/formats/iso/directory_record.rb +152 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +197 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +530 -0
- data/lib/omnizip/formats/iso.rb +140 -0
- data/lib/omnizip/formats/lzip.rb +175 -0
- data/lib/omnizip/formats/lzma_alone.rb +171 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
- data/lib/omnizip/formats/rar/block_parser.rb +243 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +82 -0
- data/lib/omnizip/formats/rar/decompressor.rb +238 -0
- data/lib/omnizip/formats/rar/external_writer.rb +312 -0
- data/lib/omnizip/formats/rar/header.rb +192 -0
- data/lib/omnizip/formats/rar/license_validator.rb +109 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
- data/lib/omnizip/formats/rar/reader.rb +366 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
- data/lib/omnizip/formats/rar/writer.rb +431 -0
- data/lib/omnizip/formats/rar.rb +205 -0
- data/lib/omnizip/formats/rar3/compressor.rb +73 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar3/reader.rb +386 -0
- data/lib/omnizip/formats/rar3/writer.rb +219 -0
- data/lib/omnizip/formats/rar5/compressor.rb +73 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar5/reader.rb +342 -0
- data/lib/omnizip/formats/rar5/writer.rb +214 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
- data/lib/omnizip/formats/seven_zip/header.rb +106 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
- data/lib/omnizip/formats/seven_zip.rb +93 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +94 -0
- data/lib/omnizip/formats/tar/header.rb +168 -0
- data/lib/omnizip/formats/tar/reader.rb +121 -0
- data/lib/omnizip/formats/tar/writer.rb +216 -0
- data/lib/omnizip/formats/tar.rb +84 -0
- data/lib/omnizip/formats/xz/reader.rb +116 -0
- data/lib/omnizip/formats/xz.rb +237 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
- data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
- data/lib/omnizip/formats/zip/reader.rb +250 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +375 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
- data/lib/omnizip/io/buffered_input.rb +146 -0
- data/lib/omnizip/io/buffered_output.rb +105 -0
- data/lib/omnizip/io/stream_manager.rb +115 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +124 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +146 -0
- data/lib/omnizip/metadata/metadata_editor.rb +171 -0
- data/lib/omnizip/metadata/metadata_registry.rb +64 -0
- data/lib/omnizip/metadata/metadata_validator.rb +99 -0
- data/lib/omnizip/metadata.rb +57 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +73 -0
- data/lib/omnizip/models/compression_options.rb +71 -0
- data/lib/omnizip/models/conversion_options.rb +87 -0
- data/lib/omnizip/models/conversion_result.rb +135 -0
- data/lib/omnizip/models/eta_result.rb +46 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +144 -0
- data/lib/omnizip/models/filter_config.rb +183 -0
- data/lib/omnizip/models/match_result.rb +124 -0
- data/lib/omnizip/models/optimization_suggestion.rb +91 -0
- data/lib/omnizip/models/parallel_options.rb +104 -0
- data/lib/omnizip/models/performance_result.rb +79 -0
- data/lib/omnizip/models/profile_report.rb +82 -0
- data/lib/omnizip/models/progress_options.rb +38 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +81 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +203 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
- data/lib/omnizip/parallel/worker_pool.rb +223 -0
- data/lib/omnizip/parallel.rb +149 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +73 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
- data/lib/omnizip/parity/models/main_packet.rb +128 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +109 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
- data/lib/omnizip/parity/par2_creator.rb +531 -0
- data/lib/omnizip/parity/par2_repairer.rb +407 -0
- data/lib/omnizip/parity/par2_verifier.rb +364 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
- data/lib/omnizip/parity.rb +186 -0
- data/lib/omnizip/password/encryption_registry.rb +65 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
- data/lib/omnizip/password.rb +87 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
- data/lib/omnizip/pipe.rb +121 -0
- data/lib/omnizip/platform/ntfs_streams.rb +201 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +39 -0
- data/lib/omnizip/profile/balanced_profile.rb +33 -0
- data/lib/omnizip/profile/binary_profile.rb +36 -0
- data/lib/omnizip/profile/compression_profile.rb +158 -0
- data/lib/omnizip/profile/custom_profile.rb +157 -0
- data/lib/omnizip/profile/fast_profile.rb +33 -0
- data/lib/omnizip/profile/maximum_profile.rb +33 -0
- data/lib/omnizip/profile/profile_detector.rb +110 -0
- data/lib/omnizip/profile/profile_registry.rb +161 -0
- data/lib/omnizip/profile/text_profile.rb +36 -0
- data/lib/omnizip/profile.rb +190 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +169 -0
- data/lib/omnizip/profiler.rb +204 -0
- data/lib/omnizip/progress/callback_reporter.rb +36 -0
- data/lib/omnizip/progress/console_reporter.rb +62 -0
- data/lib/omnizip/progress/log_reporter.rb +91 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +190 -0
- data/lib/omnizip/progress/silent_reporter.rb +24 -0
- data/lib/omnizip/progress.rb +127 -0
- data/lib/omnizip/rubyzip_compat.rb +63 -0
- data/lib/omnizip/temp/safe_extract.rb +168 -0
- data/lib/omnizip/temp/temp_file.rb +124 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +181 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +156 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +273 -0
- data/lib/omnizip/zip/output_stream.rb +324 -0
- data/lib/omnizip.rb +156 -0
- data/readme-docs/advanced-features.adoc +515 -0
- data/readme-docs/api-usage.adoc +444 -0
- data/readme-docs/architecture.adoc +449 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +442 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +325 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +617 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
# to deal in the Software without restriction, including without limitation
|
|
8
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
# DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require_relative "model"
|
|
24
|
+
require_relative "../lzma/range_encoder"
|
|
25
|
+
|
|
26
|
+
module Omnizip
|
|
27
|
+
module Algorithms
|
|
28
|
+
class PPMd8 < PPMdBase
|
|
29
|
+
# PPMd8 Encoder with enhanced features
|
|
30
|
+
#
|
|
31
|
+
# Encodes using PPMd8 model with restoration methods,
|
|
32
|
+
# run-length encoding, and improved update algorithms.
|
|
33
|
+
class Encoder
|
|
34
|
+
include PPMdBase::BaseConstants
|
|
35
|
+
include Constants
|
|
36
|
+
|
|
37
|
+
attr_reader :model
|
|
38
|
+
|
|
39
|
+
# Initialize the encoder
|
|
40
|
+
#
|
|
41
|
+
# @param output [IO] Output stream for compressed data
|
|
42
|
+
# @param options [Hash] Encoding options
|
|
43
|
+
# @option options [Integer] :model_order Maximum context order
|
|
44
|
+
# @option options [Integer] :mem_size Memory size for model
|
|
45
|
+
# @option options [Integer] :restore_method Restoration method
|
|
46
|
+
def initialize(output, options = {})
|
|
47
|
+
@output = output
|
|
48
|
+
@model = Model.new(
|
|
49
|
+
options[:model_order] || DEFAULT_ORDER,
|
|
50
|
+
options[:mem_size] || DEFAULT_MEM_SIZE,
|
|
51
|
+
options[:restore_method] || DEFAULT_RESTORE_METHOD,
|
|
52
|
+
)
|
|
53
|
+
@range_encoder = LZMA::RangeEncoder.new(output)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Encode a stream of bytes
|
|
57
|
+
#
|
|
58
|
+
# @param input [IO] Input stream to compress
|
|
59
|
+
# @return [void]
|
|
60
|
+
# @raise [NotImplementedError] PPMd8 is not yet fully implemented
|
|
61
|
+
def encode_stream(input)
|
|
62
|
+
raise NotImplementedError,
|
|
63
|
+
"PPMd8 compression is not yet fully implemented. " \
|
|
64
|
+
"The arithmetic coding integration requires completion. " \
|
|
65
|
+
"Please use PPMd7 or other compression algorithms instead."
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
# Encode a single symbol
|
|
71
|
+
#
|
|
72
|
+
# @param symbol [Integer] The byte to encode (0-255)
|
|
73
|
+
# @return [void]
|
|
74
|
+
def encode_symbol(symbol)
|
|
75
|
+
prob = @model.get_symbol_probability(symbol)
|
|
76
|
+
|
|
77
|
+
encode_range(
|
|
78
|
+
prob[:cumulative_freq],
|
|
79
|
+
prob[:freq],
|
|
80
|
+
prob[:total_freq],
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
encode_with_escape(symbol) if prob[:escape]
|
|
84
|
+
|
|
85
|
+
@model.update(symbol)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Encode with escape handling
|
|
89
|
+
#
|
|
90
|
+
# @param symbol [Integer] Symbol to encode
|
|
91
|
+
# @return [void]
|
|
92
|
+
def encode_with_escape(symbol)
|
|
93
|
+
root_prob = get_root_probability(symbol)
|
|
94
|
+
encode_range(
|
|
95
|
+
root_prob[:cumulative_freq],
|
|
96
|
+
root_prob[:freq],
|
|
97
|
+
root_prob[:total_freq],
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Get probability from root context
|
|
102
|
+
#
|
|
103
|
+
# @param symbol [Integer] Symbol to look up
|
|
104
|
+
# @return [Hash] Probability information
|
|
105
|
+
def get_root_probability(symbol)
|
|
106
|
+
context = @model.root_context
|
|
107
|
+
state = context.find_symbol(symbol)
|
|
108
|
+
|
|
109
|
+
cum_freq = 0
|
|
110
|
+
context.states.each do |sym, st|
|
|
111
|
+
break if sym >= symbol
|
|
112
|
+
|
|
113
|
+
cum_freq += st.freq
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
{
|
|
117
|
+
cumulative_freq: cum_freq,
|
|
118
|
+
freq: state.freq,
|
|
119
|
+
total_freq: context.total_freq,
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Encode a range for the symbol
|
|
124
|
+
#
|
|
125
|
+
# @param cum_freq [Integer] Cumulative frequency
|
|
126
|
+
# @param freq [Integer] Symbol frequency
|
|
127
|
+
# @param total_freq [Integer] Total frequency
|
|
128
|
+
# @return [void]
|
|
129
|
+
def encode_range(cum_freq, _freq, total_freq)
|
|
130
|
+
scale = 0x10000
|
|
131
|
+
low = (cum_freq * scale) / total_freq
|
|
132
|
+
|
|
133
|
+
@range_encoder.encode_direct_bits(low, 16)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
# to deal in the Software without restriction, including without limitation
|
|
8
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
# DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require_relative "constants"
|
|
24
|
+
require_relative "context"
|
|
25
|
+
require_relative "restoration_method"
|
|
26
|
+
|
|
27
|
+
module Omnizip
|
|
28
|
+
module Algorithms
|
|
29
|
+
class PPMd8 < PPMdBase
|
|
30
|
+
# PPMd8 prediction model with enhanced features
|
|
31
|
+
#
|
|
32
|
+
# Extends the basic PPMd model with:
|
|
33
|
+
# - Restoration methods (RESTART/CUT_OFF)
|
|
34
|
+
# - Run-length encoding for repetitions
|
|
35
|
+
# - Enhanced update algorithms
|
|
36
|
+
# - Glue count tracking for memory management
|
|
37
|
+
class Model
|
|
38
|
+
include PPMdBase::BaseConstants
|
|
39
|
+
include Constants
|
|
40
|
+
|
|
41
|
+
attr_reader :max_order, :root_context, :current_context,
|
|
42
|
+
:restoration_method, :run_length, :glue_count
|
|
43
|
+
attr_accessor :order_fall, :prev_success
|
|
44
|
+
|
|
45
|
+
# Initialize the PPMd8 model
|
|
46
|
+
#
|
|
47
|
+
# @param max_order [Integer] Maximum context order (2-16)
|
|
48
|
+
# @param mem_size [Integer] Memory size for context allocation
|
|
49
|
+
# @param restore_method [Integer] Restoration method type
|
|
50
|
+
def initialize(
|
|
51
|
+
max_order = DEFAULT_ORDER,
|
|
52
|
+
mem_size = DEFAULT_MEM_SIZE,
|
|
53
|
+
restore_method = DEFAULT_RESTORE_METHOD
|
|
54
|
+
)
|
|
55
|
+
validate_parameters(max_order, mem_size)
|
|
56
|
+
|
|
57
|
+
@max_order = max_order
|
|
58
|
+
@mem_size = mem_size
|
|
59
|
+
@restoration_method = RestorationMethod.new(restore_method)
|
|
60
|
+
|
|
61
|
+
# PPMd8-specific state
|
|
62
|
+
@run_length = 0
|
|
63
|
+
@init_rl = 0
|
|
64
|
+
@glue_count = 0
|
|
65
|
+
@order_fall = max_order
|
|
66
|
+
@prev_success = 0
|
|
67
|
+
|
|
68
|
+
# Initialize context tree
|
|
69
|
+
@root_context = Context.new(-1, nil)
|
|
70
|
+
@current_context = @root_context
|
|
71
|
+
@context_history = []
|
|
72
|
+
|
|
73
|
+
initialize_root_context
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Get probability information for a symbol
|
|
77
|
+
#
|
|
78
|
+
# @param symbol [Integer, nil] Symbol to encode (nil for decode)
|
|
79
|
+
# @return [Hash] Probability information
|
|
80
|
+
def get_symbol_probability(symbol = nil)
|
|
81
|
+
context = find_context_with_symbol(symbol)
|
|
82
|
+
|
|
83
|
+
if context && (state = context.find_symbol(symbol))
|
|
84
|
+
build_symbol_probability(context, state, symbol)
|
|
85
|
+
else
|
|
86
|
+
build_escape_probability(context || @root_context)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Update model after encoding/decoding a symbol
|
|
91
|
+
#
|
|
92
|
+
# PPMd8 uses more sophisticated update algorithms
|
|
93
|
+
#
|
|
94
|
+
# @param symbol [Integer] The symbol that was encoded/decoded
|
|
95
|
+
# @return [void]
|
|
96
|
+
def update(symbol)
|
|
97
|
+
update_run_length(symbol)
|
|
98
|
+
update_context_statistics(symbol)
|
|
99
|
+
update_current_context(symbol)
|
|
100
|
+
check_memory_restoration
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Reset model to initial state
|
|
104
|
+
#
|
|
105
|
+
# @return [void]
|
|
106
|
+
def reset
|
|
107
|
+
@root_context = Context.new(-1, nil)
|
|
108
|
+
@current_context = @root_context
|
|
109
|
+
@context_history.clear
|
|
110
|
+
@run_length = 0
|
|
111
|
+
@glue_count = 0
|
|
112
|
+
@order_fall = @max_order
|
|
113
|
+
@prev_success = 0
|
|
114
|
+
initialize_root_context
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Cut off old contexts to free memory (CUT_OFF restoration)
|
|
118
|
+
#
|
|
119
|
+
# @return [void]
|
|
120
|
+
def cut_off_old_contexts
|
|
121
|
+
# Simplified implementation - would traverse and prune
|
|
122
|
+
# contexts based on usage statistics
|
|
123
|
+
@glue_count = 0
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
# Validate initialization parameters
|
|
129
|
+
def validate_parameters(max_order, mem_size)
|
|
130
|
+
unless max_order.between?(MIN_ORDER, MAX_ORDER)
|
|
131
|
+
raise ArgumentError,
|
|
132
|
+
"max_order must be between #{MIN_ORDER} and #{MAX_ORDER}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
return if mem_size.between?(MIN_MEM_SIZE, MAX_MEM_SIZE)
|
|
136
|
+
|
|
137
|
+
raise ArgumentError,
|
|
138
|
+
"mem_size must be between #{MIN_MEM_SIZE} and " \
|
|
139
|
+
"#{MAX_MEM_SIZE}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Initialize root context
|
|
143
|
+
def initialize_root_context
|
|
144
|
+
ALPHABET_SIZE.times do |symbol|
|
|
145
|
+
@root_context.add_symbol(symbol, 1)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Build probability hash for found symbol
|
|
150
|
+
def build_symbol_probability(context, state, symbol)
|
|
151
|
+
cum_freq = cumulative_frequency(context, symbol)
|
|
152
|
+
{
|
|
153
|
+
context: context,
|
|
154
|
+
cumulative_freq: cum_freq,
|
|
155
|
+
freq: state.freq,
|
|
156
|
+
total_freq: context.total_freq,
|
|
157
|
+
escape: false,
|
|
158
|
+
}
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Build probability hash for escape
|
|
162
|
+
def build_escape_probability(context)
|
|
163
|
+
cum_freq = escape_cumulative_frequency(context)
|
|
164
|
+
{
|
|
165
|
+
context: context,
|
|
166
|
+
cumulative_freq: cum_freq,
|
|
167
|
+
freq: context.escape_freq,
|
|
168
|
+
total_freq: context.total_freq,
|
|
169
|
+
escape: true,
|
|
170
|
+
}
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Update run-length counter (PPMd8 feature)
|
|
174
|
+
def update_run_length(_symbol)
|
|
175
|
+
if @run_length.positive?
|
|
176
|
+
@run_length += 1
|
|
177
|
+
else
|
|
178
|
+
@run_length = 1
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Update context statistics
|
|
183
|
+
def update_context_statistics(symbol)
|
|
184
|
+
if @current_context.find_symbol(symbol)
|
|
185
|
+
@current_context.update_symbol(symbol)
|
|
186
|
+
else
|
|
187
|
+
@current_context.add_symbol(symbol)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Check if memory restoration is needed
|
|
192
|
+
def check_memory_restoration
|
|
193
|
+
return unless @root_context.needs_restoration?
|
|
194
|
+
|
|
195
|
+
@restoration_method.restore(self)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Find context containing symbol
|
|
199
|
+
def find_context_with_symbol(symbol)
|
|
200
|
+
return nil if symbol.nil?
|
|
201
|
+
|
|
202
|
+
context = @current_context
|
|
203
|
+
while context
|
|
204
|
+
return context if context.find_symbol(symbol)
|
|
205
|
+
|
|
206
|
+
context = context.suffix
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
nil
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Calculate cumulative frequency
|
|
213
|
+
def cumulative_frequency(context, symbol)
|
|
214
|
+
cum_freq = 0
|
|
215
|
+
context.states.each do |sym, state|
|
|
216
|
+
break if sym >= symbol
|
|
217
|
+
|
|
218
|
+
cum_freq += state.freq
|
|
219
|
+
end
|
|
220
|
+
cum_freq
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Calculate escape cumulative frequency
|
|
224
|
+
def escape_cumulative_frequency(context)
|
|
225
|
+
context.sum_freq
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Update current context
|
|
229
|
+
def update_current_context(symbol)
|
|
230
|
+
@context_history.push(symbol)
|
|
231
|
+
@context_history.shift if @context_history.size > @max_order
|
|
232
|
+
@current_context = find_or_create_context(@context_history)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Find or create context
|
|
236
|
+
def find_or_create_context(sequence)
|
|
237
|
+
return @root_context if sequence.empty?
|
|
238
|
+
|
|
239
|
+
context = @root_context
|
|
240
|
+
sequence.each_with_index do |_symbol, index|
|
|
241
|
+
suffix = index.zero? ? @root_context : context
|
|
242
|
+
context = Context.new(index, suffix)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
context
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
# to deal in the Software without restriction, including without limitation
|
|
8
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
# DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
module Omnizip
|
|
24
|
+
module Algorithms
|
|
25
|
+
class PPMd8 < PPMdBase
|
|
26
|
+
# Strategy pattern for PPMd8 restoration methods
|
|
27
|
+
#
|
|
28
|
+
# PPMd8 supports multiple restoration methods that determine
|
|
29
|
+
# how the model handles memory management and context updating
|
|
30
|
+
# when memory is exhausted.
|
|
31
|
+
class RestorationMethod
|
|
32
|
+
include Constants
|
|
33
|
+
|
|
34
|
+
attr_reader :method_type
|
|
35
|
+
|
|
36
|
+
# Initialize restoration method
|
|
37
|
+
#
|
|
38
|
+
# @param method_type [Integer] The restoration method type
|
|
39
|
+
def initialize(method_type = RESTORE_METHOD_RESTART)
|
|
40
|
+
@method_type = method_type
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Execute restoration based on the selected method
|
|
44
|
+
#
|
|
45
|
+
# @param model [Model] The PPMd8 model to restore
|
|
46
|
+
# @return [void]
|
|
47
|
+
def restore(model)
|
|
48
|
+
case @method_type
|
|
49
|
+
when RESTORE_METHOD_RESTART
|
|
50
|
+
restart_restoration(model)
|
|
51
|
+
when RESTORE_METHOD_CUT_OFF
|
|
52
|
+
cut_off_restoration(model)
|
|
53
|
+
else
|
|
54
|
+
raise ArgumentError, "Unknown restoration method: #{@method_type}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
# RESTART method: Reinitialize the model from scratch
|
|
61
|
+
#
|
|
62
|
+
# @param model [Model] The model to restore
|
|
63
|
+
# @return [void]
|
|
64
|
+
def restart_restoration(model)
|
|
65
|
+
model.reset
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# CUT_OFF method: Remove older contexts to free memory
|
|
69
|
+
#
|
|
70
|
+
# @param model [Model] The model to restore
|
|
71
|
+
# @return [void]
|
|
72
|
+
def cut_off_restoration(model)
|
|
73
|
+
model.cut_off_old_contexts
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
# to deal in the Software without restriction, including without limitation
|
|
8
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
# DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require_relative "ppmd_base"
|
|
24
|
+
require_relative "ppmd8/constants"
|
|
25
|
+
require_relative "ppmd8/restoration_method"
|
|
26
|
+
require_relative "ppmd8/context"
|
|
27
|
+
require_relative "ppmd8/model"
|
|
28
|
+
require_relative "ppmd8/encoder"
|
|
29
|
+
require_relative "ppmd8/decoder"
|
|
30
|
+
|
|
31
|
+
module Omnizip
|
|
32
|
+
module Algorithms
|
|
33
|
+
# PPMd8 (PPMdI) compression algorithm
|
|
34
|
+
#
|
|
35
|
+
# PPMd8 is an improved variant of PPMd7 that adds:
|
|
36
|
+
# - Multiple restoration methods (RESTART, CUT_OFF)
|
|
37
|
+
# - Enhanced memory management with glue counting
|
|
38
|
+
# - Improved context update algorithms
|
|
39
|
+
# - Run-length encoding support for better repetition handling
|
|
40
|
+
#
|
|
41
|
+
# This implementation follows the PPMd8 specification from 7-Zip.
|
|
42
|
+
class PPMd8 < PPMdBase
|
|
43
|
+
include Constants
|
|
44
|
+
|
|
45
|
+
# Algorithm metadata
|
|
46
|
+
#
|
|
47
|
+
# @return [AlgorithmMetadata] Metadata describing this algorithm
|
|
48
|
+
def self.metadata
|
|
49
|
+
Models::AlgorithmMetadata.new.tap do |m|
|
|
50
|
+
m.name = "ppmd8"
|
|
51
|
+
m.description = "PPMd8 (PPMdI) - Enhanced Prediction by " \
|
|
52
|
+
"Partial Matching with improved restoration"
|
|
53
|
+
m.version = "1.0.0"
|
|
54
|
+
m.supports_streaming = true
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
protected
|
|
59
|
+
|
|
60
|
+
# Create PPMd8 encoder
|
|
61
|
+
#
|
|
62
|
+
# @param output [IO] Output stream
|
|
63
|
+
# @param options [Hash] Encoding options
|
|
64
|
+
# @return [PPMd8::Encoder] Encoder instance
|
|
65
|
+
def create_encoder(output, options)
|
|
66
|
+
PPMd8::Encoder.new(output, options)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Create PPMd8 decoder
|
|
70
|
+
#
|
|
71
|
+
# @param input [IO] Input stream
|
|
72
|
+
# @param options [Hash] Decoding options
|
|
73
|
+
# @return [PPMd8::Decoder] Decoder instance
|
|
74
|
+
def create_decoder(input, options)
|
|
75
|
+
PPMd8::Decoder.new(input, options)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Register algorithm with registry
|
|
82
|
+
Omnizip::AlgorithmRegistry.register(:ppmd8, Omnizip::Algorithms::PPMd8)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
# to deal in the Software without restriction, including without limitation
|
|
8
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
# DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require_relative "../algorithm"
|
|
24
|
+
|
|
25
|
+
module Omnizip
|
|
26
|
+
module Algorithms
|
|
27
|
+
# Base class for PPMd (Prediction by Partial Matching) algorithms
|
|
28
|
+
#
|
|
29
|
+
# This abstract base class provides common functionality for PPMd
|
|
30
|
+
# variants (PPMd7, PPMd8, etc.) while allowing each variant to
|
|
31
|
+
# implement its specific features.
|
|
32
|
+
#
|
|
33
|
+
# The design follows the Template Method pattern, where common
|
|
34
|
+
# operations are defined here and variant-specific operations
|
|
35
|
+
# are delegated to subclasses.
|
|
36
|
+
class PPMdBase < Algorithm
|
|
37
|
+
# Common constants for all PPMd variants
|
|
38
|
+
module BaseConstants
|
|
39
|
+
# Context order limits
|
|
40
|
+
MIN_ORDER = 2
|
|
41
|
+
MAX_ORDER = 16
|
|
42
|
+
DEFAULT_ORDER = 6
|
|
43
|
+
|
|
44
|
+
# Memory allocation
|
|
45
|
+
MIN_MEM_SIZE = 1 << 20 # 1 MB
|
|
46
|
+
MAX_MEM_SIZE = 1 << 30 # 1 GB
|
|
47
|
+
DEFAULT_MEM_SIZE = 1 << 24 # 16 MB
|
|
48
|
+
|
|
49
|
+
# Alphabet
|
|
50
|
+
ALPHABET_SIZE = 256
|
|
51
|
+
|
|
52
|
+
# Range coder constants
|
|
53
|
+
TOP_VALUE = 1 << 24
|
|
54
|
+
BOT_VALUE = 1 << 15
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
include BaseConstants
|
|
58
|
+
|
|
59
|
+
# Compress data using PPMd variant
|
|
60
|
+
#
|
|
61
|
+
# @param input [IO, String] Input data to compress
|
|
62
|
+
# @param output [IO, String] Output for compressed data
|
|
63
|
+
# @param options [Hash] Compression options
|
|
64
|
+
# @return [void]
|
|
65
|
+
def compress(input, output, options = {})
|
|
66
|
+
input = prepare_input(input)
|
|
67
|
+
output = prepare_output(output)
|
|
68
|
+
|
|
69
|
+
encoder = create_encoder(output, options)
|
|
70
|
+
encoder.encode_stream(input)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Decompress data using PPMd variant
|
|
74
|
+
#
|
|
75
|
+
# @param input [IO, String] Compressed input data
|
|
76
|
+
# @param output [IO, String] Output for decompressed data
|
|
77
|
+
# @param options [Hash] Decompression options
|
|
78
|
+
# @return [void]
|
|
79
|
+
def decompress(input, output, options = {})
|
|
80
|
+
input = prepare_input(input)
|
|
81
|
+
output = prepare_output(output)
|
|
82
|
+
|
|
83
|
+
decoder = create_decoder(input, options)
|
|
84
|
+
result = decoder.decode_stream
|
|
85
|
+
|
|
86
|
+
output.write(result)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
protected
|
|
90
|
+
|
|
91
|
+
# Template method for creating encoder
|
|
92
|
+
# Subclasses must implement this
|
|
93
|
+
#
|
|
94
|
+
# @param output [IO] Output stream
|
|
95
|
+
# @param options [Hash] Encoding options
|
|
96
|
+
# @return [Object] Encoder instance
|
|
97
|
+
# @raise [NotImplementedError] if not implemented by subclass
|
|
98
|
+
def create_encoder(output, options)
|
|
99
|
+
raise NotImplementedError,
|
|
100
|
+
"#{self.class} must implement #create_encoder"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Template method for creating decoder
|
|
104
|
+
# Subclasses must implement this
|
|
105
|
+
#
|
|
106
|
+
# @param input [IO] Input stream
|
|
107
|
+
# @param options [Hash] Decoding options
|
|
108
|
+
# @return [Object] Decoder instance
|
|
109
|
+
# @raise [NotImplementedError] if not implemented by subclass
|
|
110
|
+
def create_decoder(input, options)
|
|
111
|
+
raise NotImplementedError,
|
|
112
|
+
"#{self.class} must implement #create_decoder"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
# Prepare input for processing
|
|
118
|
+
#
|
|
119
|
+
# @param input [IO, String] Input data
|
|
120
|
+
# @return [IO] IO object ready for reading
|
|
121
|
+
def prepare_input(input)
|
|
122
|
+
return input if input.is_a?(IO)
|
|
123
|
+
|
|
124
|
+
StringIO.new(input.to_s)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Prepare output for processing
|
|
128
|
+
#
|
|
129
|
+
# @param output [IO, String, nil] Output destination
|
|
130
|
+
# @return [IO] IO object ready for writing
|
|
131
|
+
def prepare_output(output)
|
|
132
|
+
return output if output.is_a?(IO)
|
|
133
|
+
|
|
134
|
+
StringIO.new(String.new(encoding: Encoding::BINARY))
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|