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.
Files changed (511) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +754 -0
  5. data/COPYING +502 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +12 -0
  8. data/README.adoc +1045 -0
  9. data/Rakefile +12 -0
  10. data/benchmark/README.md +260 -0
  11. data/benchmark/benchmark_suite.rb +125 -0
  12. data/benchmark/compression_bench.rb +181 -0
  13. data/benchmark/filter_bench.rb +180 -0
  14. data/benchmark/models/benchmark_result.rb +59 -0
  15. data/benchmark/models/comparison_result.rb +69 -0
  16. data/benchmark/profile_suite.rb +167 -0
  17. data/benchmark/reporter.rb +150 -0
  18. data/benchmark/run_benchmarks.rb +66 -0
  19. data/benchmark/test_data.rb +137 -0
  20. data/config/formats/rar3_spec.yml +91 -0
  21. data/config/formats/rar5_spec.yml +102 -0
  22. data/docs/.github/workflows/docs.yml +142 -0
  23. data/docs/.gitignore +21 -0
  24. data/docs/.lychee.toml +67 -0
  25. data/docs/Gemfile +13 -0
  26. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  27. data/docs/README.md +101 -0
  28. data/docs/_config.yml +112 -0
  29. data/docs/assets/logo.svg +1 -0
  30. data/docs/assets/omnizip-logo.pdf +1540 -11
  31. data/docs/comparison/feature-matrix.adoc +694 -0
  32. data/docs/comparison/index.adoc +113 -0
  33. data/docs/comparison/vs-7zip.adoc +309 -0
  34. data/docs/comparison/vs-peazip.adoc +77 -0
  35. data/docs/comparison/vs-rubyzip.adoc +342 -0
  36. data/docs/comparison/vs-winrar.adoc +100 -0
  37. data/docs/compatibility.adoc +579 -0
  38. data/docs/concepts/index.adoc +129 -0
  39. data/docs/developer/architecture.adoc +256 -0
  40. data/docs/developer/contributing.adoc +158 -0
  41. data/docs/developer/index.adoc +25 -0
  42. data/docs/developer/testing.adoc +212 -0
  43. data/docs/getting-started/basic-usage.adoc +271 -0
  44. data/docs/getting-started/index.adoc +42 -0
  45. data/docs/getting-started/installation.adoc +138 -0
  46. data/docs/getting-started/quick-start.adoc +185 -0
  47. data/docs/getting-started/your-first-archive.adoc +218 -0
  48. data/docs/guides/advanced-features/encryption.adoc +300 -0
  49. data/docs/guides/advanced-features/index.adoc +49 -0
  50. data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
  51. data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
  52. data/docs/guides/advanced-features/streaming.adoc +212 -0
  53. data/docs/guides/archive-formats/gzip-format.adoc +107 -0
  54. data/docs/guides/archive-formats/index.adoc +130 -0
  55. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  56. data/docs/guides/archive-formats/rar5.adoc +521 -0
  57. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  58. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  59. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  60. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  61. data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
  62. data/docs/guides/compression-algorithms/deflate.adoc +319 -0
  63. data/docs/guides/compression-algorithms/index.adoc +190 -0
  64. data/docs/guides/compression-algorithms/lzma.adoc +398 -0
  65. data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
  66. data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
  67. data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
  68. data/docs/guides/creating-archives.adoc +354 -0
  69. data/docs/guides/extracting-archives.adoc +53 -0
  70. data/docs/guides/format-conversion.adoc +64 -0
  71. data/docs/guides/index.adoc +49 -0
  72. data/docs/guides/migration-rubyzip.adoc +217 -0
  73. data/docs/guides/parity-archives.adoc +605 -0
  74. data/docs/guides/performance-tuning.adoc +88 -0
  75. data/docs/index.adoc +218 -0
  76. data/docs/lychee.toml +67 -0
  77. data/docs/reference/api/overview.adoc +188 -0
  78. data/docs/reference/cli/compress-command.adoc +114 -0
  79. data/docs/reference/cli/overview.adoc +140 -0
  80. data/docs/reference/index.adoc +26 -0
  81. data/docs/resources/faq.adoc +185 -0
  82. data/docs/resources/quick-reference.adoc +222 -0
  83. data/docs/troubleshooting/index.adoc +208 -0
  84. data/examples/api_comparison.rb +205 -0
  85. data/examples/deflate64_example.rb +96 -0
  86. data/examples/par2_demo.rb +121 -0
  87. data/examples/quick_start_native.rb +150 -0
  88. data/examples/quick_start_rubyzip.rb +115 -0
  89. data/examples/rubyzip_compatibility_demo.rb +194 -0
  90. data/exe/omnizip +27 -0
  91. data/lib/omnizip/algorithm.rb +130 -0
  92. data/lib/omnizip/algorithm_registry.rb +86 -0
  93. data/lib/omnizip/algorithms/.keep +0 -0
  94. data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
  95. data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
  96. data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
  97. data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
  98. data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
  99. data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
  100. data/lib/omnizip/algorithms/bzip2.rb +130 -0
  101. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  102. data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
  103. data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
  104. data/lib/omnizip/algorithms/deflate.rb +128 -0
  105. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  106. data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
  107. data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
  108. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
  109. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
  110. data/lib/omnizip/algorithms/deflate64.rb +109 -0
  111. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  112. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  113. data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
  114. data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
  115. data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
  116. data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
  117. data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
  118. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
  119. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
  120. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
  121. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
  122. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  123. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  124. data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
  125. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  126. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
  127. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
  128. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  129. data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
  130. data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
  131. data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
  132. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  133. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
  134. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
  135. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
  136. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
  137. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
  138. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
  139. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  140. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
  141. data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
  142. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
  143. data/lib/omnizip/algorithms/lzma.rb +238 -0
  144. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
  145. data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
  146. data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
  147. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
  148. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  149. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
  150. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  151. data/lib/omnizip/algorithms/lzma2.rb +141 -0
  152. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  153. data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
  154. data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
  155. data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
  156. data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
  157. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  158. data/lib/omnizip/algorithms/ppmd7.rb +116 -0
  159. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  160. data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
  161. data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
  162. data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
  163. data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
  164. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  165. data/lib/omnizip/algorithms/ppmd8.rb +82 -0
  166. data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
  167. data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
  168. data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
  169. data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
  170. data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
  171. data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
  172. data/lib/omnizip/algorithms/zstandard.rb +138 -0
  173. data/lib/omnizip/buffer/memory_archive.rb +251 -0
  174. data/lib/omnizip/buffer/memory_extractor.rb +224 -0
  175. data/lib/omnizip/buffer.rb +176 -0
  176. data/lib/omnizip/checksum_registry.rb +114 -0
  177. data/lib/omnizip/checksums/crc32.rb +100 -0
  178. data/lib/omnizip/checksums/crc64.rb +101 -0
  179. data/lib/omnizip/checksums/crc_base.rb +158 -0
  180. data/lib/omnizip/checksums/verifier.rb +131 -0
  181. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  182. data/lib/omnizip/chunked/reader.rb +78 -0
  183. data/lib/omnizip/chunked/writer.rb +120 -0
  184. data/lib/omnizip/chunked.rb +129 -0
  185. data/lib/omnizip/cli/output_formatter.rb +104 -0
  186. data/lib/omnizip/cli.rb +572 -0
  187. data/lib/omnizip/commands/.keep +0 -0
  188. data/lib/omnizip/commands/archive_create_command.rb +427 -0
  189. data/lib/omnizip/commands/archive_extract_command.rb +272 -0
  190. data/lib/omnizip/commands/archive_list_command.rb +218 -0
  191. data/lib/omnizip/commands/archive_repair_command.rb +131 -0
  192. data/lib/omnizip/commands/archive_verify_command.rb +117 -0
  193. data/lib/omnizip/commands/compress_command.rb +117 -0
  194. data/lib/omnizip/commands/decompress_command.rb +120 -0
  195. data/lib/omnizip/commands/list_command.rb +53 -0
  196. data/lib/omnizip/commands/metadata_command.rb +153 -0
  197. data/lib/omnizip/commands/parity_create_command.rb +122 -0
  198. data/lib/omnizip/commands/parity_repair_command.rb +122 -0
  199. data/lib/omnizip/commands/parity_verify_command.rb +124 -0
  200. data/lib/omnizip/commands/profile_list_command.rb +56 -0
  201. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  202. data/lib/omnizip/convenience.rb +359 -0
  203. data/lib/omnizip/converter/conversion_registry.rb +49 -0
  204. data/lib/omnizip/converter/conversion_strategy.rb +121 -0
  205. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
  206. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
  207. data/lib/omnizip/converter.rb +105 -0
  208. data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
  209. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  210. data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
  211. data/lib/omnizip/crypto/aes256.rb +102 -0
  212. data/lib/omnizip/error.rb +106 -0
  213. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
  214. data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
  215. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  216. data/lib/omnizip/eta/sample_history.rb +143 -0
  217. data/lib/omnizip/eta/time_estimator.rb +106 -0
  218. data/lib/omnizip/eta.rb +63 -0
  219. data/lib/omnizip/extraction/filter_chain.rb +177 -0
  220. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  221. data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
  222. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  223. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  224. data/lib/omnizip/extraction/selective_extractor.rb +240 -0
  225. data/lib/omnizip/extraction.rb +111 -0
  226. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  227. data/lib/omnizip/file_type.rb +113 -0
  228. data/lib/omnizip/filter.rb +139 -0
  229. data/lib/omnizip/filter_pipeline.rb +108 -0
  230. data/lib/omnizip/filter_registry.rb +166 -0
  231. data/lib/omnizip/filters/bcj.rb +279 -0
  232. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  233. data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
  234. data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
  235. data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
  236. data/lib/omnizip/filters/bcj2.rb +99 -0
  237. data/lib/omnizip/filters/bcj_arm.rb +176 -0
  238. data/lib/omnizip/filters/bcj_arm64.rb +244 -0
  239. data/lib/omnizip/filters/bcj_ia64.rb +196 -0
  240. data/lib/omnizip/filters/bcj_ppc.rb +190 -0
  241. data/lib/omnizip/filters/bcj_sparc.rb +176 -0
  242. data/lib/omnizip/filters/bcj_x86.rb +193 -0
  243. data/lib/omnizip/filters/delta.rb +196 -0
  244. data/lib/omnizip/filters/filter_base.rb +72 -0
  245. data/lib/omnizip/filters/registry.rb +123 -0
  246. data/lib/omnizip/filters/xz_delta.rb +258 -0
  247. data/lib/omnizip/format_detector.rb +162 -0
  248. data/lib/omnizip/format_registry.rb +59 -0
  249. data/lib/omnizip/formats/.keep +0 -0
  250. data/lib/omnizip/formats/bzip2_file.rb +172 -0
  251. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  252. data/lib/omnizip/formats/cpio/entry.rb +385 -0
  253. data/lib/omnizip/formats/cpio/reader.rb +196 -0
  254. data/lib/omnizip/formats/cpio/writer.rb +234 -0
  255. data/lib/omnizip/formats/cpio.rb +140 -0
  256. data/lib/omnizip/formats/format_spec_loader.rb +230 -0
  257. data/lib/omnizip/formats/gzip.rb +238 -0
  258. data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
  259. data/lib/omnizip/formats/iso/directory_record.rb +152 -0
  260. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  261. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  262. data/lib/omnizip/formats/iso/reader.rb +197 -0
  263. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  264. data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
  265. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  266. data/lib/omnizip/formats/iso/writer.rb +530 -0
  267. data/lib/omnizip/formats/iso.rb +140 -0
  268. data/lib/omnizip/formats/lzip.rb +175 -0
  269. data/lib/omnizip/formats/lzma_alone.rb +171 -0
  270. data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
  271. data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
  272. data/lib/omnizip/formats/rar/block_parser.rb +243 -0
  273. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  274. data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
  275. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
  276. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
  277. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  278. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  279. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  280. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  281. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
  282. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
  283. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
  284. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  285. data/lib/omnizip/formats/rar/constants.rb +82 -0
  286. data/lib/omnizip/formats/rar/decompressor.rb +238 -0
  287. data/lib/omnizip/formats/rar/external_writer.rb +312 -0
  288. data/lib/omnizip/formats/rar/header.rb +192 -0
  289. data/lib/omnizip/formats/rar/license_validator.rb +109 -0
  290. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  291. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  292. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  293. data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
  294. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
  295. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
  296. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  297. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  298. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
  299. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  300. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
  301. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  302. data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
  303. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  304. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  305. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  306. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  307. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  308. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
  309. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  310. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
  311. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
  312. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
  313. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  314. data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
  315. data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
  316. data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
  317. data/lib/omnizip/formats/rar/reader.rb +366 -0
  318. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  319. data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
  320. data/lib/omnizip/formats/rar/writer.rb +431 -0
  321. data/lib/omnizip/formats/rar.rb +205 -0
  322. data/lib/omnizip/formats/rar3/compressor.rb +73 -0
  323. data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
  324. data/lib/omnizip/formats/rar3/reader.rb +386 -0
  325. data/lib/omnizip/formats/rar3/writer.rb +219 -0
  326. data/lib/omnizip/formats/rar5/compressor.rb +73 -0
  327. data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
  328. data/lib/omnizip/formats/rar5/reader.rb +342 -0
  329. data/lib/omnizip/formats/rar5/writer.rb +214 -0
  330. data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
  331. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  332. data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
  333. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
  334. data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
  335. data/lib/omnizip/formats/seven_zip/header.rb +106 -0
  336. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
  337. data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
  338. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  339. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
  340. data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
  341. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  342. data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
  343. data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
  344. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
  345. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
  346. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  347. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
  348. data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
  349. data/lib/omnizip/formats/seven_zip.rb +93 -0
  350. data/lib/omnizip/formats/tar/constants.rb +73 -0
  351. data/lib/omnizip/formats/tar/entry.rb +94 -0
  352. data/lib/omnizip/formats/tar/header.rb +168 -0
  353. data/lib/omnizip/formats/tar/reader.rb +121 -0
  354. data/lib/omnizip/formats/tar/writer.rb +216 -0
  355. data/lib/omnizip/formats/tar.rb +84 -0
  356. data/lib/omnizip/formats/xz/reader.rb +116 -0
  357. data/lib/omnizip/formats/xz.rb +237 -0
  358. data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
  359. data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
  360. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  361. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
  362. data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
  363. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  364. data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
  365. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
  366. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
  367. data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
  368. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
  369. data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
  370. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
  371. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  372. data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
  373. data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
  374. data/lib/omnizip/formats/zip/constants.rb +69 -0
  375. data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
  376. data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
  377. data/lib/omnizip/formats/zip/reader.rb +250 -0
  378. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  379. data/lib/omnizip/formats/zip/writer.rb +375 -0
  380. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
  381. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
  382. data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
  383. data/lib/omnizip/formats/zip.rb +50 -0
  384. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  385. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  386. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  387. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  388. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  389. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
  390. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
  391. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
  392. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
  393. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
  394. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
  395. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
  396. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
  397. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
  398. data/lib/omnizip/io/buffered_input.rb +146 -0
  399. data/lib/omnizip/io/buffered_output.rb +105 -0
  400. data/lib/omnizip/io/stream_manager.rb +115 -0
  401. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  402. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  403. data/lib/omnizip/link_handler.rb +124 -0
  404. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  405. data/lib/omnizip/metadata/entry_metadata.rb +146 -0
  406. data/lib/omnizip/metadata/metadata_editor.rb +171 -0
  407. data/lib/omnizip/metadata/metadata_registry.rb +64 -0
  408. data/lib/omnizip/metadata/metadata_validator.rb +99 -0
  409. data/lib/omnizip/metadata.rb +57 -0
  410. data/lib/omnizip/models/.keep +0 -0
  411. data/lib/omnizip/models/algorithm_metadata.rb +73 -0
  412. data/lib/omnizip/models/compression_options.rb +71 -0
  413. data/lib/omnizip/models/conversion_options.rb +87 -0
  414. data/lib/omnizip/models/conversion_result.rb +135 -0
  415. data/lib/omnizip/models/eta_result.rb +46 -0
  416. data/lib/omnizip/models/extraction_rule.rb +115 -0
  417. data/lib/omnizip/models/filter_chain.rb +144 -0
  418. data/lib/omnizip/models/filter_config.rb +183 -0
  419. data/lib/omnizip/models/match_result.rb +124 -0
  420. data/lib/omnizip/models/optimization_suggestion.rb +91 -0
  421. data/lib/omnizip/models/parallel_options.rb +104 -0
  422. data/lib/omnizip/models/performance_result.rb +79 -0
  423. data/lib/omnizip/models/profile_report.rb +82 -0
  424. data/lib/omnizip/models/progress_options.rb +38 -0
  425. data/lib/omnizip/models/split_options.rb +116 -0
  426. data/lib/omnizip/optimization_registry.rb +81 -0
  427. data/lib/omnizip/parallel/job_queue.rb +209 -0
  428. data/lib/omnizip/parallel/job_scheduler.rb +203 -0
  429. data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
  430. data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
  431. data/lib/omnizip/parallel/worker_pool.rb +223 -0
  432. data/lib/omnizip/parallel.rb +149 -0
  433. data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
  434. data/lib/omnizip/parity/galois16.rb +145 -0
  435. data/lib/omnizip/parity/models/creator_packet.rb +73 -0
  436. data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
  437. data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
  438. data/lib/omnizip/parity/models/main_packet.rb +128 -0
  439. data/lib/omnizip/parity/models/packet.rb +156 -0
  440. data/lib/omnizip/parity/models/packet_registry.rb +109 -0
  441. data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
  442. data/lib/omnizip/parity/par2_creator.rb +531 -0
  443. data/lib/omnizip/parity/par2_repairer.rb +407 -0
  444. data/lib/omnizip/parity/par2_verifier.rb +364 -0
  445. data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
  446. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  447. data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
  448. data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
  449. data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
  450. data/lib/omnizip/parity.rb +186 -0
  451. data/lib/omnizip/password/encryption_registry.rb +65 -0
  452. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  453. data/lib/omnizip/password/password_validator.rb +129 -0
  454. data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
  455. data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
  456. data/lib/omnizip/password.rb +87 -0
  457. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  458. data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
  459. data/lib/omnizip/pipe.rb +121 -0
  460. data/lib/omnizip/platform/ntfs_streams.rb +201 -0
  461. data/lib/omnizip/platform.rb +189 -0
  462. data/lib/omnizip/profile/archive_profile.rb +39 -0
  463. data/lib/omnizip/profile/balanced_profile.rb +33 -0
  464. data/lib/omnizip/profile/binary_profile.rb +36 -0
  465. data/lib/omnizip/profile/compression_profile.rb +158 -0
  466. data/lib/omnizip/profile/custom_profile.rb +157 -0
  467. data/lib/omnizip/profile/fast_profile.rb +33 -0
  468. data/lib/omnizip/profile/maximum_profile.rb +33 -0
  469. data/lib/omnizip/profile/profile_detector.rb +110 -0
  470. data/lib/omnizip/profile/profile_registry.rb +161 -0
  471. data/lib/omnizip/profile/text_profile.rb +36 -0
  472. data/lib/omnizip/profile.rb +190 -0
  473. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  474. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  475. data/lib/omnizip/profiler/report_generator.rb +169 -0
  476. data/lib/omnizip/profiler.rb +204 -0
  477. data/lib/omnizip/progress/callback_reporter.rb +36 -0
  478. data/lib/omnizip/progress/console_reporter.rb +62 -0
  479. data/lib/omnizip/progress/log_reporter.rb +91 -0
  480. data/lib/omnizip/progress/operation_progress.rb +118 -0
  481. data/lib/omnizip/progress/progress_bar.rb +156 -0
  482. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  483. data/lib/omnizip/progress/progress_tracker.rb +190 -0
  484. data/lib/omnizip/progress/silent_reporter.rb +24 -0
  485. data/lib/omnizip/progress.rb +127 -0
  486. data/lib/omnizip/rubyzip_compat.rb +63 -0
  487. data/lib/omnizip/temp/safe_extract.rb +168 -0
  488. data/lib/omnizip/temp/temp_file.rb +124 -0
  489. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  490. data/lib/omnizip/temp.rb +181 -0
  491. data/lib/omnizip/version.rb +5 -0
  492. data/lib/omnizip/zip/entry.rb +156 -0
  493. data/lib/omnizip/zip/file.rb +485 -0
  494. data/lib/omnizip/zip/input_stream.rb +273 -0
  495. data/lib/omnizip/zip/output_stream.rb +324 -0
  496. data/lib/omnizip.rb +156 -0
  497. data/readme-docs/advanced-features.adoc +515 -0
  498. data/readme-docs/api-usage.adoc +444 -0
  499. data/readme-docs/architecture.adoc +449 -0
  500. data/readme-docs/archive-formats.adoc +479 -0
  501. data/readme-docs/cli-usage.adoc +222 -0
  502. data/readme-docs/compression-algorithms.adoc +442 -0
  503. data/readme-docs/compression-profiles.adoc +247 -0
  504. data/readme-docs/encryption-checksums.adoc +328 -0
  505. data/readme-docs/format-converter.adoc +325 -0
  506. data/readme-docs/installation.adoc +228 -0
  507. data/readme-docs/par2-archives.adoc +608 -0
  508. data/readme-docs/performance-profiler.adoc +389 -0
  509. data/readme-docs/preprocessing-filters.adoc +280 -0
  510. data/xz-file-format-1.2.1.txt +1174 -0
  511. metadata +617 -0
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tempfile"
4
+
5
+ module Omnizip
6
+ module Chunked
7
+ # Manage memory usage and enforce limits during chunked operations
8
+ class MemoryManager
9
+ DEFAULT_MAX_MEMORY = 256 * 1024 * 1024 # 256MB
10
+
11
+ attr_reader :current_usage, :max_memory
12
+
13
+ # Initialize memory manager
14
+ # @param options [Hash] Manager options
15
+ # @option options [Integer] :max Maximum memory in bytes
16
+ # @option options [String] :temp_dir Temporary directory for spill files
17
+ # @option options [Symbol] :strategy Spill strategy (:disk or :error)
18
+ def initialize(max: DEFAULT_MAX_MEMORY, temp_dir: nil, strategy: :disk)
19
+ @max_memory = max
20
+ @current_usage = 0
21
+ @buffers = {} # buffer => size mapping
22
+ @temp_files = []
23
+ @temp_dir = temp_dir
24
+ @strategy = strategy
25
+ end
26
+
27
+ # Allocate memory or spill to disk
28
+ # @param size [Integer] Size to allocate in bytes
29
+ # @return [String, Tempfile] Buffer or temp file
30
+ def allocate(size)
31
+ if can_allocate_in_memory?(size)
32
+ allocate_buffer(size)
33
+ else
34
+ handle_overflow(size)
35
+ end
36
+ end
37
+
38
+ # Release allocated memory or temp file
39
+ # @param buffer [String, Tempfile] Buffer to release
40
+ # @return [Integer] Bytes released
41
+ def release(buffer)
42
+ case buffer
43
+ when String
44
+ release_buffer(buffer)
45
+ when Tempfile, File
46
+ release_temp_file(buffer)
47
+ else
48
+ 0
49
+ end
50
+ end
51
+
52
+ # Get available memory
53
+ # @return [Integer] Available memory in bytes
54
+ def available
55
+ [@max_memory - @current_usage, 0].max
56
+ end
57
+
58
+ # Check if over memory limit
59
+ # @return [Boolean] True if over limit
60
+ def over_limit?
61
+ @current_usage > @max_memory
62
+ end
63
+
64
+ # Get memory usage ratio
65
+ # @return [Float] Usage from 0.0 to 1.0
66
+ def usage_ratio
67
+ return 0.0 if @max_memory.zero?
68
+
69
+ @current_usage.to_f / @max_memory
70
+ end
71
+
72
+ # Cleanup all resources
73
+ # @return [self]
74
+ def cleanup
75
+ @buffers.clear
76
+ @temp_files.each do |tf|
77
+ begin
78
+ tf.close
79
+ rescue StandardError
80
+ nil
81
+ end
82
+ begin
83
+ tf.unlink
84
+ rescue StandardError
85
+ nil
86
+ end
87
+ end
88
+ @temp_files.clear
89
+ @current_usage = 0
90
+ self
91
+ end
92
+
93
+ # Execute block with automatic cleanup
94
+ # @yield [manager] Block to execute with manager
95
+ # @return [Object] Block result
96
+ def self.with_manager(**options)
97
+ manager = new(**options)
98
+ begin
99
+ yield manager
100
+ ensure
101
+ manager.cleanup
102
+ end
103
+ end
104
+
105
+ # Spill buffer to disk
106
+ # @param buffer [String] Buffer data to spill
107
+ # @return [Tempfile] Temporary file
108
+ def spill_to_disk(buffer = nil)
109
+ tf = create_temp_file
110
+ tf.write(buffer) if buffer
111
+ tf.rewind
112
+ @temp_files << tf
113
+ tf
114
+ end
115
+
116
+ private
117
+
118
+ # Check if size can be allocated in memory
119
+ def can_allocate_in_memory?(size)
120
+ @current_usage + size <= @max_memory
121
+ end
122
+
123
+ # Allocate in-memory buffer
124
+ def allocate_buffer(size)
125
+ buffer = String.new(capacity: size, encoding: Encoding::BINARY)
126
+ @buffers[buffer] = size
127
+ @current_usage += size
128
+ buffer
129
+ end
130
+
131
+ # Release in-memory buffer
132
+ def release_buffer(buffer)
133
+ size = @buffers.delete(buffer)
134
+ if size
135
+ @current_usage -= size
136
+ size
137
+ else
138
+ 0
139
+ end
140
+ end
141
+
142
+ # Release temp file
143
+ def release_temp_file(file)
144
+ if @temp_files.delete(file)
145
+ size = begin
146
+ file.size
147
+ rescue StandardError
148
+ 0
149
+ end
150
+ begin
151
+ file.close
152
+ rescue StandardError
153
+ nil
154
+ end
155
+ begin
156
+ file.unlink
157
+ rescue StandardError
158
+ nil
159
+ end
160
+ size
161
+ else
162
+ 0
163
+ end
164
+ end
165
+
166
+ # Handle memory overflow based on strategy
167
+ def handle_overflow(size)
168
+ case @strategy
169
+ when :disk
170
+ spill_to_disk
171
+ when :error
172
+ message = "Memory limit exceeded: " \
173
+ "#{@current_usage + size} > #{@max_memory}"
174
+ raise MemoryError, message
175
+ else
176
+ raise ArgumentError, "Unknown spill strategy: #{@strategy}"
177
+ end
178
+ end
179
+
180
+ # Create temporary file
181
+ def create_temp_file
182
+ Tempfile.new(
183
+ ["omnizip_chunk_", ".tmp"],
184
+ @temp_dir,
185
+ binmode: true,
186
+ )
187
+ end
188
+ end
189
+
190
+ # Error raised when memory limit is exceeded
191
+ class MemoryError < Omnizip::Error
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Chunked
5
+ # Read large files in chunks for memory-efficient processing
6
+ class Reader
7
+ DEFAULT_CHUNK_SIZE = 64 * 1024 * 1024 # 64MB
8
+
9
+ attr_reader :file_path, :chunk_size, :total_size
10
+
11
+ # Initialize a chunked reader
12
+ # @param file_path [String] Path to file to read
13
+ # @param options [Hash] Reader options
14
+ # @option options [Integer] :chunk_size Chunk size in bytes
15
+ def initialize(file_path, chunk_size: DEFAULT_CHUNK_SIZE)
16
+ @file_path = file_path
17
+ @chunk_size = chunk_size
18
+ @total_size = File.size(file_path)
19
+ @position = 0
20
+ end
21
+
22
+ # Read next chunk from file
23
+ # @return [String, nil] Chunk data or nil if EOF
24
+ def read_chunk
25
+ return nil if @position >= @total_size
26
+
27
+ File.open(@file_path, "rb") do |f|
28
+ f.seek(@position)
29
+ chunk = f.read(@chunk_size)
30
+ @position += chunk.bytesize if chunk
31
+ chunk
32
+ end
33
+ end
34
+
35
+ # Iterate through all chunks
36
+ # @yield [chunk, position, total] Block called for each chunk
37
+ def each_chunk
38
+ reset
39
+ while (chunk = read_chunk)
40
+ yield chunk, @position - chunk.bytesize, @total_size
41
+ end
42
+ end
43
+
44
+ # Get current progress as percentage
45
+ # @return [Float] Progress from 0.0 to 1.0
46
+ def progress
47
+ return 1.0 if @total_size.zero?
48
+
49
+ @position.to_f / @total_size
50
+ end
51
+
52
+ # Reset reader to beginning of file
53
+ # @return [self]
54
+ def reset
55
+ @position = 0
56
+ self
57
+ end
58
+
59
+ # Check if at end of file
60
+ # @return [Boolean] True if at EOF
61
+ def eof?
62
+ @position >= @total_size
63
+ end
64
+
65
+ # Get number of chunks needed for file
66
+ # @return [Integer] Number of chunks
67
+ def chunk_count
68
+ (@total_size.to_f / @chunk_size).ceil
69
+ end
70
+
71
+ # Get remaining bytes to read
72
+ # @return [Integer] Remaining bytes
73
+ def remaining
74
+ @total_size - @position
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Chunked
5
+ # Write large files incrementally in chunks
6
+ class Writer
7
+ DEFAULT_CHUNK_SIZE = 64 * 1024 * 1024 # 64MB
8
+ FLUSH_THRESHOLD = 10 # Flush every N chunks
9
+
10
+ attr_reader :output_path, :chunk_size, :written
11
+
12
+ # Initialize a chunked writer
13
+ # @param output_path [String] Path to output file
14
+ # @param options [Hash] Writer options
15
+ # @option options [Integer] :chunk_size Chunk size in bytes
16
+ def initialize(output_path, chunk_size: DEFAULT_CHUNK_SIZE)
17
+ @output_path = output_path
18
+ @chunk_size = chunk_size
19
+ @written = 0
20
+ @chunks_written = 0
21
+ @file_handle = nil
22
+ end
23
+
24
+ # Write a chunk to file
25
+ # @param chunk [String] Data to write
26
+ # @return [Integer] Bytes written
27
+ def write_chunk(chunk)
28
+ ensure_file_open
29
+
30
+ bytes = @file_handle.write(chunk)
31
+ @written += bytes
32
+ @chunks_written += 1
33
+
34
+ # Flush periodically to disk
35
+ flush if (@chunks_written % FLUSH_THRESHOLD).zero?
36
+
37
+ bytes
38
+ end
39
+
40
+ # Write data from a source in chunks
41
+ # @param source [String, IO] Source to read from
42
+ # @return [Integer] Total bytes written
43
+ def write_from(source)
44
+ case source
45
+ when String
46
+ # File path
47
+ if File.exist?(source)
48
+ Reader.new(source, chunk_size: @chunk_size).each_chunk do |chunk|
49
+ write_chunk(chunk)
50
+ end
51
+ else
52
+ # Treat as data
53
+ write_chunk(source)
54
+ end
55
+ when IO, StringIO
56
+ # IO object
57
+ while (chunk = source.read(@chunk_size))
58
+ break if chunk.empty?
59
+
60
+ write_chunk(chunk)
61
+ end
62
+ else
63
+ raise ArgumentError, "Unsupported source type: #{source.class}"
64
+ end
65
+
66
+ @written
67
+ end
68
+
69
+ # Flush buffered data to disk
70
+ # @return [self]
71
+ def flush
72
+ @file_handle&.flush
73
+ self
74
+ end
75
+
76
+ # Close the file handle
77
+ # @return [self]
78
+ def close
79
+ if @file_handle
80
+ flush
81
+ @file_handle.close
82
+ @file_handle = nil
83
+ end
84
+ self
85
+ end
86
+
87
+ # Finalize the file (alias for close)
88
+ # @return [self]
89
+ def finish
90
+ close
91
+ end
92
+
93
+ # Execute block with writer, auto-close
94
+ # @yield [writer] Block to write data
95
+ # @return [Integer] Total bytes written
96
+ def self.with_writer(output_path, **options)
97
+ writer = new(output_path, **options)
98
+ begin
99
+ yield writer
100
+ writer.written
101
+ ensure
102
+ writer.close
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ # Ensure file handle is open
109
+ def ensure_file_open
110
+ return if @file_handle
111
+
112
+ # Create parent directory if needed
113
+ dir = File.dirname(@output_path)
114
+ FileUtils.mkdir_p(dir)
115
+
116
+ @file_handle = File.open(@output_path, "wb")
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ # Chunked processing for memory-efficient large file handling
5
+ module Chunked
6
+ # Configuration for chunked operations
7
+ class Configuration
8
+ attr_accessor :chunk_size, :max_memory, :temp_directory, :spill_strategy
9
+
10
+ def initialize
11
+ @chunk_size = 64 * 1024 * 1024 # 64MB
12
+ @max_memory = 256 * 1024 * 1024 # 256MB
13
+ @temp_directory = nil # Use system default
14
+ @spill_strategy = :disk # or :error
15
+ end
16
+ end
17
+
18
+ class << self
19
+ # Global configuration
20
+ def configuration
21
+ @configuration ||= Configuration.new
22
+ end
23
+
24
+ # Configure chunked operations
25
+ # @yield [config] Configuration block
26
+ def configure
27
+ yield configuration
28
+ end
29
+
30
+ # Compress file with chunked processing
31
+ # @param input [String] Input file path
32
+ # @param output [String] Output file path
33
+ # @param options [Hash] Compression options
34
+ # @option options [Integer] :chunk_size Chunk size in bytes
35
+ # @option options [Integer] :max_memory Maximum memory usage in bytes
36
+ # @option options [Symbol] :compression Compression method
37
+ # @option options [Proc] :progress Progress callback
38
+ # @return [String] Output file path
39
+ def compress_file(input, output, **options)
40
+ chunk_size = options[:chunk_size] || configuration.chunk_size
41
+ options[:max_memory] || configuration.max_memory
42
+ progress = options[:progress]
43
+
44
+ unless File.exist?(input)
45
+ raise Errno::ENOENT,
46
+ "Input file not found: #{input}"
47
+ end
48
+
49
+ reader = Reader.new(input, chunk_size: chunk_size)
50
+ total_size = reader.total_size
51
+ processed = 0
52
+
53
+ Omnizip::Zip::File.create(output) do |zip|
54
+ basename = File.basename(input)
55
+
56
+ # Use add with a block instead of private add_data
57
+ zip.add(basename) do
58
+ data = String.new(encoding: Encoding::BINARY)
59
+
60
+ reader.each_chunk do |chunk|
61
+ data << chunk
62
+ processed += chunk.bytesize
63
+
64
+ if progress
65
+ percentage = (processed.to_f / total_size * 100).round(2)
66
+ progress.call(processed, total_size, percentage)
67
+ end
68
+ end
69
+
70
+ data
71
+ end
72
+ end
73
+
74
+ output
75
+ end
76
+
77
+ # Decompress file with chunked processing
78
+ # @param input [String] Input archive path
79
+ # @param output [String] Output file path
80
+ # @param options [Hash] Decompression options
81
+ # @option options [Integer] :chunk_size Chunk size in bytes
82
+ # @option options [Proc] :progress Progress callback
83
+ # @return [String] Output file path
84
+ def decompress_file(input, output, **options)
85
+ chunk_size = options[:chunk_size] || configuration.chunk_size
86
+ progress = options[:progress]
87
+
88
+ unless File.exist?(input)
89
+ raise Errno::ENOENT,
90
+ "Input archive not found: #{input}"
91
+ end
92
+
93
+ writer = Writer.new(output, chunk_size: chunk_size)
94
+ processed = 0
95
+
96
+ Omnizip::Zip::File.open(input) do |zip|
97
+ entry = zip.entries.first
98
+ total_size = entry.size
99
+
100
+ # Read the full entry content
101
+ content = zip.get_input_stream(entry)
102
+
103
+ # Write in chunks
104
+ offset = 0
105
+ while offset < content.bytesize
106
+ chunk = content.byteslice(offset, chunk_size) || ""
107
+ break if chunk.empty?
108
+
109
+ writer.write_chunk(chunk)
110
+ processed += chunk.bytesize
111
+ offset += chunk.bytesize
112
+
113
+ if progress
114
+ percentage = (processed.to_f / total_size * 100).round(2)
115
+ progress.call(processed, total_size, percentage)
116
+ end
117
+ end
118
+ end
119
+
120
+ writer.close
121
+ output
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ require_relative "chunked/reader"
128
+ require_relative "chunked/writer"
129
+ require_relative "chunked/memory_manager"
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (C) 2024 Ribose Inc.
5
+ #
6
+ # This file is part of Omnizip.
7
+ #
8
+ # Omnizip is a pure Ruby port of 7-Zip compression algorithms.
9
+ # Based on the 7-Zip LZMA SDK by Igor Pavlov.
10
+ #
11
+ # This library is free software; you can redistribute it and/or
12
+ # modify it under the terms of the GNU Lesser General Public
13
+ # License as published by the Free Software Foundation; either
14
+ # version 2.1 of the License, or (at your option) any later version.
15
+ #
16
+ # See the COPYING file for the complete text of the license.
17
+ #
18
+
19
+ module Omnizip
20
+ # Output formatting utilities for CLI commands.
21
+ #
22
+ # Provides methods for formatting compression statistics, error messages,
23
+ # and other CLI output in a user-friendly manner.
24
+ module CliOutputFormatter
25
+ class << self
26
+ # Format compression statistics for display.
27
+ #
28
+ # @param input_size [Integer] Original size in bytes
29
+ # @param output_size [Integer] Compressed size in bytes
30
+ # @param elapsed_time [Float] Time taken in seconds
31
+ # @return [String] Formatted statistics
32
+ def format_compression_stats(input_size, output_size, elapsed_time)
33
+ ratio = if input_size.positive?
34
+ (output_size.to_f / input_size * 100).round(2)
35
+ else
36
+ 0.0
37
+ end
38
+
39
+ [
40
+ "Input size: #{format_size(input_size)}",
41
+ "Output size: #{format_size(output_size)}",
42
+ "Ratio: #{ratio}%",
43
+ "Time: #{elapsed_time.round(3)}s",
44
+ ].join("\n")
45
+ end
46
+
47
+ # Format file size in human-readable format.
48
+ #
49
+ # @param bytes [Integer] Size in bytes
50
+ # @return [String] Formatted size
51
+ def format_size(bytes)
52
+ units = %w[B KB MB GB TB]
53
+ return "0 B" if bytes.zero?
54
+
55
+ exp = (Math.log(bytes) / Math.log(1024)).floor
56
+ exp = [exp, units.length - 1].min
57
+
58
+ size = (bytes.to_f / (1024**exp)).round(2)
59
+ "#{size} #{units[exp]}"
60
+ end
61
+
62
+ # Format error message for display.
63
+ #
64
+ # @param error [Exception] The error object
65
+ # @return [String] Formatted error message
66
+ def format_error(error)
67
+ "Error: #{error.message}"
68
+ end
69
+
70
+ # Format algorithm information as a table.
71
+ #
72
+ # @param algorithms [Array<Models::AlgorithmMetadata>] Algorithms
73
+ # @return [String] Formatted table
74
+ def format_algorithms_table(algorithms)
75
+ return "No algorithms registered." if algorithms.empty?
76
+
77
+ lines = []
78
+ lines << "Available compression algorithms:"
79
+ lines << ""
80
+
81
+ max_name = algorithms.map { |a| a.name.to_s.length }.max
82
+ max_desc = algorithms.map { |a| a.description.length }.max
83
+
84
+ algorithms.each do |algo|
85
+ name = algo.name.to_s.ljust(max_name)
86
+ desc = algo.description.ljust(max_desc)
87
+ version = "v#{algo.version}"
88
+ lines << " #{name} - #{desc} (#{version})"
89
+ end
90
+
91
+ lines.join("\n")
92
+ end
93
+
94
+ # Print verbose message if verbose mode is enabled.
95
+ #
96
+ # @param message [String] The message to print
97
+ # @param verbose [Boolean] Whether verbose mode is enabled
98
+ # @return [void]
99
+ def verbose_puts(message, verbose)
100
+ puts message if verbose
101
+ end
102
+ end
103
+ end
104
+ end