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,127 @@
|
|
|
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 LZMA < Algorithm
|
|
26
|
+
# LZMA State Machine for managing compression states
|
|
27
|
+
#
|
|
28
|
+
# This class implements the state machine used by LZMA to track
|
|
29
|
+
# the current compression context. The state determines which
|
|
30
|
+
# probability models are used for encoding the next symbol.
|
|
31
|
+
#
|
|
32
|
+
# LZMA uses 12 states that transition based on the type of
|
|
33
|
+
# symbol being encoded (literal, match, rep match, etc.).
|
|
34
|
+
# The state affects probability model selection for better
|
|
35
|
+
# compression.
|
|
36
|
+
class State
|
|
37
|
+
# Total number of LZMA states
|
|
38
|
+
NUM_STATES = 12
|
|
39
|
+
|
|
40
|
+
# State transition tables
|
|
41
|
+
# After encoding a literal
|
|
42
|
+
LIT_STATES = [0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5].freeze
|
|
43
|
+
|
|
44
|
+
# After encoding a match
|
|
45
|
+
MATCH_STATES = [7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10].freeze
|
|
46
|
+
|
|
47
|
+
# After encoding a rep match
|
|
48
|
+
REP_STATES = [8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11].freeze
|
|
49
|
+
|
|
50
|
+
# After encoding a short rep
|
|
51
|
+
SHORT_REP_STATES = [9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11].freeze
|
|
52
|
+
|
|
53
|
+
attr_reader :index
|
|
54
|
+
|
|
55
|
+
# Initialize the state machine
|
|
56
|
+
#
|
|
57
|
+
# @param initial_state [Integer] Initial state index (default: 0)
|
|
58
|
+
def initialize(initial_state = 0)
|
|
59
|
+
@index = initial_state
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Update state after encoding a literal
|
|
63
|
+
#
|
|
64
|
+
# @return [void]
|
|
65
|
+
def update_literal
|
|
66
|
+
@index = LIT_STATES[@index]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Update state after encoding a match
|
|
70
|
+
#
|
|
71
|
+
# @return [void]
|
|
72
|
+
def update_match
|
|
73
|
+
@index = MATCH_STATES[@index]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Update state after encoding a repeat match
|
|
77
|
+
#
|
|
78
|
+
# @return [void]
|
|
79
|
+
def update_rep
|
|
80
|
+
@index = REP_STATES[@index]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Update state after encoding a short repeat match
|
|
84
|
+
#
|
|
85
|
+
# @return [void]
|
|
86
|
+
def update_short_rep
|
|
87
|
+
@index = SHORT_REP_STATES[@index]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Check if current state is a literal state
|
|
91
|
+
#
|
|
92
|
+
# @return [Boolean] True if state < 7
|
|
93
|
+
def literal?
|
|
94
|
+
@index < 7
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Check if current state is a match state
|
|
98
|
+
#
|
|
99
|
+
# @return [Boolean] True if state >= 7
|
|
100
|
+
def match?
|
|
101
|
+
@index >= 7
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Reset state to initial value
|
|
105
|
+
#
|
|
106
|
+
# @return [void]
|
|
107
|
+
def reset
|
|
108
|
+
@index = 0
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Create a copy of this state
|
|
112
|
+
#
|
|
113
|
+
# @return [State] A new State with the same index
|
|
114
|
+
def dup
|
|
115
|
+
State.new(@index)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Get state index for probability model selection
|
|
119
|
+
#
|
|
120
|
+
# @return [Integer] Current state index
|
|
121
|
+
def to_i
|
|
122
|
+
@index
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
|
|
5
|
+
require_relative "range_coder"
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Algorithms
|
|
9
|
+
class LZMA < Algorithm
|
|
10
|
+
# XZ Utils-compatible buffered range encoder
|
|
11
|
+
#
|
|
12
|
+
# This encoder queues symbols for deferred encoding, matching
|
|
13
|
+
# XZ Utils' architecture. This enables:
|
|
14
|
+
# - Price calculation without actual encoding
|
|
15
|
+
# - Optimal parsing with lookahead
|
|
16
|
+
# - Output size limiting for LZMA2
|
|
17
|
+
#
|
|
18
|
+
# Based on: xz/src/liblzma/rangecoder/range_encoder.h
|
|
19
|
+
class XzBufferedRangeEncoder < RangeCoder
|
|
20
|
+
# Symbol types (matching XZ Utils enum)
|
|
21
|
+
RC_BIT_0 = :bit_0
|
|
22
|
+
RC_BIT_1 = :bit_1
|
|
23
|
+
RC_DIRECT_0 = :direct_0
|
|
24
|
+
RC_DIRECT_1 = :direct_1
|
|
25
|
+
RC_FLUSH = :flush
|
|
26
|
+
|
|
27
|
+
# Maximum symbols that can be queued
|
|
28
|
+
RC_SYMBOLS_MAX = 53
|
|
29
|
+
|
|
30
|
+
# Symbol queue entry
|
|
31
|
+
SymbolEntry = Struct.new(:type, :prob, keyword_init: true)
|
|
32
|
+
|
|
33
|
+
# Mutable probability model for XZ Utils encoder
|
|
34
|
+
# Unlike BitModel, this has a mutable value attribute for inline updates
|
|
35
|
+
class Probability
|
|
36
|
+
include Constants
|
|
37
|
+
|
|
38
|
+
attr_accessor :value
|
|
39
|
+
|
|
40
|
+
def initialize(initial_value = BIT_MODEL_TOTAL >> 1)
|
|
41
|
+
@value = initial_value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Update the probability model based on an actual bit value
|
|
45
|
+
# Compatibility with BitModel interface
|
|
46
|
+
def update(bit)
|
|
47
|
+
if bit.zero?
|
|
48
|
+
@value += ((BIT_MODEL_TOTAL - @value) >> MOVE_BITS)
|
|
49
|
+
else
|
|
50
|
+
@value -= (@value >> MOVE_BITS)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Compatibility with BitModel interface
|
|
55
|
+
alias probability value
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
attr_reader :out_total, :count
|
|
59
|
+
|
|
60
|
+
# Return bytes needed for decoding
|
|
61
|
+
#
|
|
62
|
+
# @return [Integer] Number of bytes decoder will consume
|
|
63
|
+
def bytes_for_decode
|
|
64
|
+
@out_total
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Initialize buffered range encoder
|
|
68
|
+
#
|
|
69
|
+
# @param output_stream [IO] The output stream for encoded bytes
|
|
70
|
+
def initialize(output_stream)
|
|
71
|
+
super
|
|
72
|
+
@cache = 0
|
|
73
|
+
@cache_size = 1 # XZ starts with 1, not 0
|
|
74
|
+
@out_total = 0
|
|
75
|
+
|
|
76
|
+
# Symbol queue
|
|
77
|
+
@symbols = []
|
|
78
|
+
@probs = []
|
|
79
|
+
@count = 0
|
|
80
|
+
@pos = 0
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Reset encoder to initial state
|
|
84
|
+
# NOTE: @out_total is NOT reset here - it tracks cumulative output across chunks
|
|
85
|
+
# and should only be initialized in initialize()
|
|
86
|
+
def reset
|
|
87
|
+
@low = 0
|
|
88
|
+
@cache_size = 1
|
|
89
|
+
@range = 0xFFFFFFFF
|
|
90
|
+
@cache = 0
|
|
91
|
+
@count = 0
|
|
92
|
+
@pos = 0
|
|
93
|
+
@symbols.clear
|
|
94
|
+
@probs.clear
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Queue a bit for encoding (deferred)
|
|
98
|
+
#
|
|
99
|
+
# @param prob [BitModel] Probability model
|
|
100
|
+
# @param bit [Integer] Bit value (0 or 1)
|
|
101
|
+
def queue_bit(prob, bit)
|
|
102
|
+
raise "Symbol buffer overflow" if @count >= RC_SYMBOLS_MAX
|
|
103
|
+
|
|
104
|
+
@symbols[@count] = bit.zero? ? RC_BIT_0 : RC_BIT_1
|
|
105
|
+
@probs[@count] = prob
|
|
106
|
+
@count += 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Queue direct bits for encoding (deferred)
|
|
110
|
+
#
|
|
111
|
+
# @param value [Integer] Value to encode
|
|
112
|
+
# @param num_bits [Integer] Number of bits
|
|
113
|
+
def queue_direct_bits(value, num_bits)
|
|
114
|
+
num_bits.downto(1) do |i|
|
|
115
|
+
bit = (value >> (i - 1)) & 1
|
|
116
|
+
raise "Symbol buffer overflow" if @count >= RC_SYMBOLS_MAX
|
|
117
|
+
|
|
118
|
+
@symbols[@count] = bit.zero? ? RC_DIRECT_0 : RC_DIRECT_1
|
|
119
|
+
@probs[@count] = nil
|
|
120
|
+
@count += 1
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Queue flush operation
|
|
125
|
+
def queue_flush
|
|
126
|
+
5.times do
|
|
127
|
+
raise "Symbol buffer overflow" if @count >= RC_SYMBOLS_MAX
|
|
128
|
+
|
|
129
|
+
@symbols[@count] = RC_FLUSH
|
|
130
|
+
@probs[@count] = nil
|
|
131
|
+
@count += 1
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Encode all queued symbols to output
|
|
136
|
+
#
|
|
137
|
+
# @param out [IO,String] Output buffer
|
|
138
|
+
# @param out_pos [Integer] Current output position
|
|
139
|
+
# @param out_size [Integer] Output buffer size
|
|
140
|
+
# @return [Boolean] True if output buffer filled before encoding complete
|
|
141
|
+
def encode_symbols(out, out_pos, out_size)
|
|
142
|
+
while @pos < @count
|
|
143
|
+
symbol = @symbols[@pos]
|
|
144
|
+
|
|
145
|
+
# Check if this is a flush symbol BEFORE normalization
|
|
146
|
+
is_flush = (symbol == RC_FLUSH)
|
|
147
|
+
|
|
148
|
+
# Normalize if range too small (skip during flush mode)
|
|
149
|
+
# Important: normalization may need multiple iterations and buffer fills
|
|
150
|
+
while @range < TOP && !is_flush
|
|
151
|
+
# Try to write a byte
|
|
152
|
+
if shift_low_buffered(out, out_pos, out_size)
|
|
153
|
+
# Buffer full - update range anyway so we make progress on next call
|
|
154
|
+
@range <<= 8
|
|
155
|
+
return true
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Successfully shifted, update range
|
|
159
|
+
@range <<= 8
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Track whether we should increment @pos after the case statement
|
|
163
|
+
increment_pos = true
|
|
164
|
+
|
|
165
|
+
# Encode current symbol
|
|
166
|
+
case symbol
|
|
167
|
+
when RC_BIT_0
|
|
168
|
+
prob = @probs[@pos]
|
|
169
|
+
bound = (@range >> 11) * prob.value
|
|
170
|
+
|
|
171
|
+
@range = bound
|
|
172
|
+
# XZ Utils inline probability update for bit=0
|
|
173
|
+
prob.value += (BIT_MODEL_TOTAL - prob.value) >> MOVE_BITS
|
|
174
|
+
when RC_BIT_1
|
|
175
|
+
prob = @probs[@pos]
|
|
176
|
+
bound = (@range >> 11) * prob.value
|
|
177
|
+
|
|
178
|
+
@low += bound
|
|
179
|
+
@range -= bound
|
|
180
|
+
# XZ Utils inline probability update for bit=1
|
|
181
|
+
prob.value -= prob.value >> MOVE_BITS
|
|
182
|
+
when RC_DIRECT_0
|
|
183
|
+
# Direct bit 0: @range >>= 1 (matches XZ Utils rc_direct pattern where dest += 0)
|
|
184
|
+
@range >>= 1
|
|
185
|
+
when RC_DIRECT_1
|
|
186
|
+
# Direct bit 1: @range >>= 1; @low += @range (matches XZ Utils rc_direct pattern)
|
|
187
|
+
@range >>= 1
|
|
188
|
+
@low += @range
|
|
189
|
+
when RC_FLUSH
|
|
190
|
+
# Prevent further normalization (XZ Utils sets range to UINT32_MAX)
|
|
191
|
+
@range = 0xFFFFFFFF
|
|
192
|
+
|
|
193
|
+
# CRITICAL: XZ Utils processes ALL remaining flush symbols in a tight loop
|
|
194
|
+
# before resetting. The loop does: do { rc_shift_low } while (++rc->pos < rc->count)
|
|
195
|
+
# This means it processes the current flush symbol, increments pos, then
|
|
196
|
+
# checks if there are more symbols to process.
|
|
197
|
+
loop do
|
|
198
|
+
# XZ Utils behavior: when low=0 and cache=0, no useful bytes can be written
|
|
199
|
+
# We consume the RC_FLUSH symbol but don't write output
|
|
200
|
+
# After writing cache+carry, if no new cache value and cache_size=0, we're done
|
|
201
|
+
low32 = @low & 0xFFFFFFFF
|
|
202
|
+
high = @low >> 32
|
|
203
|
+
(low32 >> 24) & 0xFF
|
|
204
|
+
|
|
205
|
+
# If low and cache are both zero, and cache_size is 0 or 1, we're done
|
|
206
|
+
# (cache_size will be 1 after setting new_cache, or 0 if it was 0 and new_cache is 0)
|
|
207
|
+
break if low32.zero? && high.zero? && @cache.zero? && @cache_size <= 1
|
|
208
|
+
|
|
209
|
+
# Process this flush symbol (write one byte)
|
|
210
|
+
if shift_low_buffered(out, out_pos, out_size)
|
|
211
|
+
# Buffer full - pause and resume later
|
|
212
|
+
return true
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Increment position (matches ++rc->pos in XZ Utils)
|
|
216
|
+
@pos += 1
|
|
217
|
+
|
|
218
|
+
# Check if we should continue (matches ++rc->pos < rc->count in XZ Utils)
|
|
219
|
+
# Continue while there are more symbols AND the next symbol is also RC_FLUSH
|
|
220
|
+
break unless @pos < @count && @symbols[@pos] == RC_FLUSH
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# After all flush symbols processed, reset encoder state (like XZ Utils)
|
|
224
|
+
reset
|
|
225
|
+
@count = 0
|
|
226
|
+
# Don't increment @pos again - it was already incremented in the loop
|
|
227
|
+
increment_pos = false
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Increment position for non-flush symbols (flush symbols increment in the loop)
|
|
231
|
+
@pos += 1 if increment_pos
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# All symbols encoded (flush returns early with @count = 0)
|
|
235
|
+
@count = 0
|
|
236
|
+
@pos = 0
|
|
237
|
+
false
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Forget queued symbols (e.g., when output limit reached)
|
|
241
|
+
def forget
|
|
242
|
+
raise "Cannot forget with partial encoding" unless @pos.zero?
|
|
243
|
+
|
|
244
|
+
@count = 0
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Get number of pending output bytes
|
|
248
|
+
#
|
|
249
|
+
# @return [Integer] Pending bytes count
|
|
250
|
+
def pending
|
|
251
|
+
@cache_size + 5 - 1
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Check if there are no queued symbols
|
|
255
|
+
#
|
|
256
|
+
# @return [Boolean] True if no symbols queued
|
|
257
|
+
def none?
|
|
258
|
+
@count.zero?
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
private
|
|
262
|
+
|
|
263
|
+
# Shift low byte to output (buffered version)
|
|
264
|
+
#
|
|
265
|
+
# @param out [IO,String] Output buffer
|
|
266
|
+
# @param out_pos [Ref<Integer>] Current output position (modified)
|
|
267
|
+
# @param out_size [Integer] Output buffer size
|
|
268
|
+
# @return [Boolean] True if buffer full
|
|
269
|
+
def shift_low_buffered(out, out_pos, out_size)
|
|
270
|
+
low32 = @low & 0xFFFFFFFF
|
|
271
|
+
high = @low >> 32
|
|
272
|
+
|
|
273
|
+
# During flush mode, force output of cache byte even if cache_size=0
|
|
274
|
+
flush_mode = (@range == 0xFFFFFFFF)
|
|
275
|
+
|
|
276
|
+
# XZ Utils: Write bytes if low32 < 0xFF000000 OR high != 0
|
|
277
|
+
# During flush mode, ALWAYS write at least one byte
|
|
278
|
+
if low32 < 0xFF000000 || high != 0 || flush_mode
|
|
279
|
+
# Output cache + carry, then pending 0xFF bytes
|
|
280
|
+
# In flush mode, write at least one byte (the cache)
|
|
281
|
+
loop_count = flush_mode && @cache_size.zero? ? 1 : @cache_size
|
|
282
|
+
|
|
283
|
+
while loop_count.positive?
|
|
284
|
+
if out_pos.value >= out_size
|
|
285
|
+
return true
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
output_byte = (@cache + high) & 0xFF
|
|
289
|
+
|
|
290
|
+
if out.is_a?(String)
|
|
291
|
+
out.setbyte(out_pos.value, output_byte)
|
|
292
|
+
else
|
|
293
|
+
out.putc(output_byte)
|
|
294
|
+
end
|
|
295
|
+
out_pos.value += 1
|
|
296
|
+
@out_total += 1
|
|
297
|
+
|
|
298
|
+
@cache = 0xFF # Set cache to 0xFF for pending bytes
|
|
299
|
+
|
|
300
|
+
loop_count -= 1
|
|
301
|
+
@cache_size -= 1 if @cache_size.positive?
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
@cache = (low32 >> 24) & 0xFF
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# XZ Utils: ALWAYS increment cache_size, even during flush mode
|
|
308
|
+
# This is critical for correct encoder behavior
|
|
309
|
+
@cache_size += 1
|
|
310
|
+
@low = (low32 << 8) & 0xFFFFFFFF
|
|
311
|
+
false
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Reference wrapper for integer (for out_pos parameter)
|
|
316
|
+
class IntRef
|
|
317
|
+
attr_accessor :value
|
|
318
|
+
|
|
319
|
+
def initialize(val)
|
|
320
|
+
@value = val
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|