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,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
require_relative "../../../../../../lib/omnizip/algorithms/lzma"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Formats
|
|
8
|
+
module Rar
|
|
9
|
+
module Rar5
|
|
10
|
+
module Solid
|
|
11
|
+
# Solid LZMA encoder with persistent dictionary
|
|
12
|
+
#
|
|
13
|
+
# This encoder maintains LZMA dictionary state across multiple files,
|
|
14
|
+
# allowing later files to reference data from earlier files. This is
|
|
15
|
+
# the core technique behind solid compression's improved ratios.
|
|
16
|
+
#
|
|
17
|
+
# Unlike normal compression where each file is independent, solid
|
|
18
|
+
# compression treats all files as one continuous stream, maximizing
|
|
19
|
+
# dictionary-based compression efficiency.
|
|
20
|
+
#
|
|
21
|
+
# @example Compress multiple files in solid mode
|
|
22
|
+
# encoder = SolidEncoder.new(level: 5)
|
|
23
|
+
# compressed = encoder.compress_stream(concatenated_data)
|
|
24
|
+
class SolidEncoder
|
|
25
|
+
# @return [Integer] Compression level (1-5)
|
|
26
|
+
attr_reader :level
|
|
27
|
+
|
|
28
|
+
# @return [Hash] LZMA options
|
|
29
|
+
attr_reader :lzma_options
|
|
30
|
+
|
|
31
|
+
# Initialize solid encoder
|
|
32
|
+
#
|
|
33
|
+
# @param options [Hash] Encoder options
|
|
34
|
+
# @option options [Integer] :level Compression level (1-5, default: 3)
|
|
35
|
+
def initialize(options = {})
|
|
36
|
+
@level = options[:level] || 3
|
|
37
|
+
@lzma_options = build_lzma_options(@level)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Compress data with persistent dictionary
|
|
41
|
+
#
|
|
42
|
+
# @param data [String] Data to compress (concatenated files)
|
|
43
|
+
# @return [String] Compressed data
|
|
44
|
+
def compress_stream(data)
|
|
45
|
+
input = StringIO.new(data)
|
|
46
|
+
output = StringIO.new
|
|
47
|
+
output.set_encoding(Encoding::BINARY)
|
|
48
|
+
|
|
49
|
+
# Create LZMA encoder
|
|
50
|
+
lzma = Algorithms::LZMA.new
|
|
51
|
+
|
|
52
|
+
# Compress entire stream at once (maintains dictionary)
|
|
53
|
+
lzma.compress(input, output, @lzma_options)
|
|
54
|
+
|
|
55
|
+
output.string
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Decompress solid stream
|
|
59
|
+
#
|
|
60
|
+
# @param data [String] Compressed data
|
|
61
|
+
# @return [String] Decompressed data
|
|
62
|
+
def decompress_stream(data)
|
|
63
|
+
input = StringIO.new(data)
|
|
64
|
+
output = StringIO.new
|
|
65
|
+
output.set_encoding(Encoding::BINARY)
|
|
66
|
+
|
|
67
|
+
lzma = Algorithms::LZMA.new
|
|
68
|
+
lzma.decompress(input, output)
|
|
69
|
+
|
|
70
|
+
output.string
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Build LZMA options for solid compression
|
|
74
|
+
#
|
|
75
|
+
# Solid compression benefits from larger dictionaries since
|
|
76
|
+
# we're compressing more data at once.
|
|
77
|
+
#
|
|
78
|
+
# @param level [Integer] RAR5 compression level (1-5)
|
|
79
|
+
# @return [LzmaOptions] LZMA encoder options
|
|
80
|
+
def build_lzma_options(level)
|
|
81
|
+
# Use larger dictionaries for solid mode
|
|
82
|
+
# This allows better cross-file references
|
|
83
|
+
dict_size = 1 << case level
|
|
84
|
+
when 1 then 20 # 1 MB (fastest)
|
|
85
|
+
when 2 then 22 # 4 MB (fast)
|
|
86
|
+
when 3 then 24 # 16 MB (normal)
|
|
87
|
+
when 4 then 25 # 32 MB (good)
|
|
88
|
+
when 5 then 26 # 64 MB (best)
|
|
89
|
+
else 24 # default: 16 MB
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
LzmaOptions.new(level, dict_size)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Simple options class for LZMA parameters
|
|
96
|
+
class LzmaOptions
|
|
97
|
+
attr_reader :level, :dict_size
|
|
98
|
+
|
|
99
|
+
def initialize(level, dict_size)
|
|
100
|
+
@level = level
|
|
101
|
+
@dict_size = dict_size
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "solid_stream"
|
|
4
|
+
require_relative "solid_encoder"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Formats
|
|
8
|
+
module Rar
|
|
9
|
+
module Rar5
|
|
10
|
+
module Solid
|
|
11
|
+
# Solid compression manager
|
|
12
|
+
#
|
|
13
|
+
# This manager coordinates solid compression by:
|
|
14
|
+
# 1. Collecting files into a SolidStream
|
|
15
|
+
# 2. Compressing the entire stream with persistent dictionary
|
|
16
|
+
# 3. Tracking file boundaries for extraction
|
|
17
|
+
#
|
|
18
|
+
# The result is better compression ratios at the cost of:
|
|
19
|
+
# - Cannot extract individual files without decompressing entire solid block
|
|
20
|
+
# - Corruption in one file may affect others in the same block
|
|
21
|
+
#
|
|
22
|
+
# @example Create solid archive
|
|
23
|
+
# manager = SolidManager.new(level: 5)
|
|
24
|
+
# manager.add_file('file1.txt', data1)
|
|
25
|
+
# manager.add_file('file2.txt', data2)
|
|
26
|
+
# compressed = manager.compress_all
|
|
27
|
+
class SolidManager
|
|
28
|
+
# @return [SolidStream] File stream
|
|
29
|
+
attr_reader :stream
|
|
30
|
+
|
|
31
|
+
# @return [SolidEncoder] Compression encoder
|
|
32
|
+
attr_reader :encoder
|
|
33
|
+
|
|
34
|
+
# @return [Integer] Compression level
|
|
35
|
+
attr_reader :level
|
|
36
|
+
|
|
37
|
+
# Initialize solid manager
|
|
38
|
+
#
|
|
39
|
+
# @param options [Hash] Options
|
|
40
|
+
# @option options [Integer] :level Compression level (1-5, default: 3)
|
|
41
|
+
def initialize(options = {})
|
|
42
|
+
@level = options[:level] || 3
|
|
43
|
+
@stream = SolidStream.new
|
|
44
|
+
@encoder = SolidEncoder.new(level: @level)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Add file to solid block
|
|
48
|
+
#
|
|
49
|
+
# @param filename [String] File name
|
|
50
|
+
# @param data [String] File data
|
|
51
|
+
# @param metadata [Hash] File metadata
|
|
52
|
+
# @return [void]
|
|
53
|
+
def add_file(filename, data, metadata = {})
|
|
54
|
+
@stream.add_file(filename, data, metadata)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Compress all files in solid mode
|
|
58
|
+
#
|
|
59
|
+
# Returns compressed data and file metadata needed for headers.
|
|
60
|
+
#
|
|
61
|
+
# @return [Hash] Compressed result
|
|
62
|
+
# @option result [String] :compressed_data The compressed stream
|
|
63
|
+
# @option result [Integer] :compressed_size Size of compressed data
|
|
64
|
+
# @option result [Integer] :uncompressed_size Total uncompressed size
|
|
65
|
+
# @option result [Array<Hash>] :files File metadata with offsets
|
|
66
|
+
def compress_all
|
|
67
|
+
# Get concatenated data
|
|
68
|
+
data = @stream.concatenated_data
|
|
69
|
+
|
|
70
|
+
# Compress entire stream
|
|
71
|
+
compressed = @encoder.compress_stream(data)
|
|
72
|
+
|
|
73
|
+
{
|
|
74
|
+
compressed_data: compressed,
|
|
75
|
+
compressed_size: compressed.bytesize,
|
|
76
|
+
uncompressed_size: data.bytesize,
|
|
77
|
+
files: @stream.files.dup,
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Decompress solid stream and extract file
|
|
82
|
+
#
|
|
83
|
+
# @param compressed_data [String] Compressed data
|
|
84
|
+
# @param file_index [Integer] File index to extract
|
|
85
|
+
# @return [String, nil] File data or nil if not found
|
|
86
|
+
def extract_file(compressed_data, file_index)
|
|
87
|
+
# Validate index
|
|
88
|
+
return nil if file_index.negative? || file_index >= @stream.file_count
|
|
89
|
+
|
|
90
|
+
# Decompress entire stream
|
|
91
|
+
decompressed = @encoder.decompress_stream(compressed_data)
|
|
92
|
+
|
|
93
|
+
# Extract specific file
|
|
94
|
+
file = @stream.file_at(file_index)
|
|
95
|
+
return nil unless file
|
|
96
|
+
|
|
97
|
+
decompressed[file[:offset], file[:size]]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Get file count
|
|
101
|
+
#
|
|
102
|
+
# @return [Integer] Number of files
|
|
103
|
+
def file_count
|
|
104
|
+
@stream.file_count
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Get total uncompressed size
|
|
108
|
+
#
|
|
109
|
+
# @return [Integer] Total size in bytes
|
|
110
|
+
def total_size
|
|
111
|
+
@stream.total_size
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Check if manager has files
|
|
115
|
+
#
|
|
116
|
+
# @return [Boolean] true if files added
|
|
117
|
+
def has_files?
|
|
118
|
+
!@stream.empty?
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Clear all data
|
|
122
|
+
#
|
|
123
|
+
# @return [void]
|
|
124
|
+
def clear
|
|
125
|
+
@stream.clear
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Calculate compression ratio
|
|
129
|
+
#
|
|
130
|
+
# @param compressed_size [Integer] Compressed data size
|
|
131
|
+
# @return [Float] Compression ratio (0.0-1.0)
|
|
132
|
+
def compression_ratio(compressed_size)
|
|
133
|
+
return 0.0 if total_size.zero?
|
|
134
|
+
|
|
135
|
+
compressed_size.to_f / total_size
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Rar
|
|
6
|
+
module Rar5
|
|
7
|
+
module Solid
|
|
8
|
+
# Solid stream for concatenating multiple files
|
|
9
|
+
#
|
|
10
|
+
# In solid compression, multiple files are concatenated into a single
|
|
11
|
+
# compression stream, allowing the compressor to use data from earlier
|
|
12
|
+
# files as dictionary/context for later files. This significantly
|
|
13
|
+
# improves compression ratios for similar files.
|
|
14
|
+
#
|
|
15
|
+
# The stream maintains file boundaries and metadata to enable proper
|
|
16
|
+
# extraction while keeping all data in one continuous buffer.
|
|
17
|
+
#
|
|
18
|
+
# @example Create solid stream with multiple files
|
|
19
|
+
# stream = SolidStream.new
|
|
20
|
+
# stream.add_file('file1.txt', File.binread('file1.txt'))
|
|
21
|
+
# stream.add_file('file2.txt', File.binread('file2.txt'))
|
|
22
|
+
# data = stream.concatenated_data
|
|
23
|
+
class SolidStream
|
|
24
|
+
# @return [Array<Hash>] File entries with metadata
|
|
25
|
+
attr_reader :files
|
|
26
|
+
|
|
27
|
+
# @return [String] Concatenated file data
|
|
28
|
+
attr_reader :concatenated_data
|
|
29
|
+
|
|
30
|
+
# Initialize solid stream
|
|
31
|
+
def initialize
|
|
32
|
+
@files = []
|
|
33
|
+
@concatenated_data = String.new(encoding: Encoding::BINARY)
|
|
34
|
+
@current_offset = 0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Add file to solid stream
|
|
38
|
+
#
|
|
39
|
+
# @param filename [String] File name for archive
|
|
40
|
+
# @param data [String] File data (binary)
|
|
41
|
+
# @param metadata [Hash] Additional file metadata
|
|
42
|
+
# @option metadata [Time] :mtime Modification time
|
|
43
|
+
# @option metadata [File::Stat] :stat File stat object
|
|
44
|
+
# @return [void]
|
|
45
|
+
def add_file(filename, data, metadata = {})
|
|
46
|
+
# Store file information
|
|
47
|
+
file_entry = {
|
|
48
|
+
filename: filename,
|
|
49
|
+
offset: @current_offset,
|
|
50
|
+
size: data.bytesize,
|
|
51
|
+
mtime: metadata[:mtime],
|
|
52
|
+
stat: metadata[:stat],
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@files << file_entry
|
|
56
|
+
|
|
57
|
+
# Append data to stream
|
|
58
|
+
@concatenated_data << data
|
|
59
|
+
|
|
60
|
+
# Update offset
|
|
61
|
+
@current_offset += data.bytesize
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Get total size of all files
|
|
65
|
+
#
|
|
66
|
+
# @return [Integer] Total size in bytes
|
|
67
|
+
def total_size
|
|
68
|
+
@concatenated_data.bytesize
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Get file count
|
|
72
|
+
#
|
|
73
|
+
# @return [Integer] Number of files
|
|
74
|
+
def file_count
|
|
75
|
+
@files.size
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Get file entry by index
|
|
79
|
+
#
|
|
80
|
+
# @param index [Integer] File index (0-based)
|
|
81
|
+
# @return [Hash, nil] File entry or nil if not found
|
|
82
|
+
def file_at(index)
|
|
83
|
+
return nil if index.negative? || index >= @files.size
|
|
84
|
+
|
|
85
|
+
@files[index]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Extract file data by index
|
|
89
|
+
#
|
|
90
|
+
# @param index [Integer] File index (0-based)
|
|
91
|
+
# @return [String, nil] File data or nil if not found
|
|
92
|
+
def extract_file_data(index)
|
|
93
|
+
return nil if index.negative? || index >= @files.size
|
|
94
|
+
|
|
95
|
+
file = @files[index]
|
|
96
|
+
return nil unless file
|
|
97
|
+
|
|
98
|
+
@concatenated_data[file[:offset], file[:size]]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Clear all data and reset
|
|
102
|
+
#
|
|
103
|
+
# @return [void]
|
|
104
|
+
def clear
|
|
105
|
+
@files.clear
|
|
106
|
+
@concatenated_data.clear
|
|
107
|
+
@current_offset = 0
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Check if stream is empty
|
|
111
|
+
#
|
|
112
|
+
# @return [Boolean] true if no files added
|
|
113
|
+
def empty?
|
|
114
|
+
@files.empty?
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Rar
|
|
6
|
+
module Rar5
|
|
7
|
+
# Variable-length integer encoding/decoding for RAR5 format
|
|
8
|
+
module VINT
|
|
9
|
+
# Encode integer as VINT bytes
|
|
10
|
+
# @param value [Integer] Value to encode (0 to 2^62)
|
|
11
|
+
# @return [Array<Integer>] VINT bytes
|
|
12
|
+
def self.encode(value)
|
|
13
|
+
return [value] if value < 0x80
|
|
14
|
+
|
|
15
|
+
bytes = []
|
|
16
|
+
# Determine byte count needed
|
|
17
|
+
byte_count = 1
|
|
18
|
+
test_value = value
|
|
19
|
+
while test_value >= (1 << (7 * byte_count))
|
|
20
|
+
byte_count += 1
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# First byte: continuation bits + high bits
|
|
24
|
+
first_byte = (0xFF << (9 - byte_count)) & 0xFF
|
|
25
|
+
first_byte |= (value >> (8 * (byte_count - 1))) & 0x7F
|
|
26
|
+
bytes << first_byte
|
|
27
|
+
|
|
28
|
+
# Remaining bytes
|
|
29
|
+
(byte_count - 1).downto(1) do |i|
|
|
30
|
+
bytes << ((value >> (8 * (i - 1))) & 0xFF)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
bytes
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Decode VINT from IO stream
|
|
37
|
+
# @param io [IO] Input stream
|
|
38
|
+
# @return [Integer] Decoded value
|
|
39
|
+
def self.decode(io)
|
|
40
|
+
first_byte = io.readbyte
|
|
41
|
+
return first_byte if first_byte < 0x80
|
|
42
|
+
|
|
43
|
+
# Count continuation bits
|
|
44
|
+
byte_count = 0
|
|
45
|
+
mask = 0x80
|
|
46
|
+
while first_byte.anybits?(mask)
|
|
47
|
+
byte_count += 1
|
|
48
|
+
mask >>= 1
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Extract value from first byte
|
|
52
|
+
value = first_byte & (0xFF >> (byte_count + 1))
|
|
53
|
+
|
|
54
|
+
# Read remaining bytes
|
|
55
|
+
byte_count.times do
|
|
56
|
+
value = (value << 8) | io.readbyte
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
value
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|